1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2d2709c7cSDavid Howells #include <linux/hw_breakpoint.h> 38dd2a131SJiri Olsa #include <linux/err.h> 4347c2f0aSIan Rogers #include <linux/list_sort.h> 57f7c536fSArnaldo Carvalho de Melo #include <linux/zalloc.h> 676b31a29SArnaldo Carvalho de Melo #include <dirent.h> 7a43783aeSArnaldo Carvalho de Melo #include <errno.h> 886a5e0c2SArnaldo Carvalho de Melo #include <sys/ioctl.h> 9391e4206SArnaldo Carvalho de Melo #include <sys/param.h> 10b0742e90SArnaldo Carvalho de Melo #include "term.h" 11361c99a6SArnaldo Carvalho de Melo #include "evlist.h" 1269aad6f1SArnaldo Carvalho de Melo #include "evsel.h" 134b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h> 1486470930SIngo Molnar #include "parse-events.h" 15a067558eSArnaldo Carvalho de Melo #include "string2.h" 167a6e9164SIan Rogers #include "strbuf.h" 176e81c74cSMasami Hiramatsu #include "debug.h" 18592d5a6bSJiri Olsa #include <api/fs/tracing_path.h> 199c3516d1SJiri Olsa #include <perf/cpumap.h> 20c7e97f21SNamhyung Kim #include <util/parse-events-bison.h> 21c7e97f21SNamhyung Kim #include <util/parse-events-flex.h> 225f537a26SJiri Olsa #include "pmu.h" 231eaf496eSIan Rogers #include "pmus.h" 24b39b8393SJiri Olsa #include "asm/bug.h" 25ac12f676SAndi Kleen #include "util/parse-branch-options.h" 2695be9d19SArnaldo Carvalho de Melo #include "util/evsel_config.h" 27252a2fdcSArnaldo Carvalho de Melo #include "util/event.h" 28d180aa56SNamhyung Kim #include "util/bpf-filter.h" 29ea0c5239SIan Rogers #include "util/util.h" 309b7c7728SIan Rogers #include "tracepoint.h" 3189812fc8SJiri Olsa 3289812fc8SJiri Olsa #define MAX_NAME_LEN 100 3386470930SIngo Molnar 345ccc4edfSIan Rogers static int get_config_terms(const struct parse_events_terms *head_config, 355ccc4edfSIan Rogers struct list_head *head_terms); 360d3f0e6fSIan Rogers static int parse_events_terms__copy(const struct parse_events_terms *src, 370d3f0e6fSIan Rogers struct parse_events_terms *dest); 38bcd3279fSFrederic Weisbecker 394a20e793SIan Rogers const struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = { 401dc12760SJiri Olsa [PERF_COUNT_HW_CPU_CYCLES] = { 411dc12760SJiri Olsa .symbol = "cpu-cycles", 421dc12760SJiri Olsa .alias = "cycles", 431dc12760SJiri Olsa }, 441dc12760SJiri Olsa [PERF_COUNT_HW_INSTRUCTIONS] = { 451dc12760SJiri Olsa .symbol = "instructions", 461dc12760SJiri Olsa .alias = "", 471dc12760SJiri Olsa }, 481dc12760SJiri Olsa [PERF_COUNT_HW_CACHE_REFERENCES] = { 491dc12760SJiri Olsa .symbol = "cache-references", 501dc12760SJiri Olsa .alias = "", 511dc12760SJiri Olsa }, 521dc12760SJiri Olsa [PERF_COUNT_HW_CACHE_MISSES] = { 531dc12760SJiri Olsa .symbol = "cache-misses", 541dc12760SJiri Olsa .alias = "", 551dc12760SJiri Olsa }, 561dc12760SJiri Olsa [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { 571dc12760SJiri Olsa .symbol = "branch-instructions", 581dc12760SJiri Olsa .alias = "branches", 591dc12760SJiri Olsa }, 601dc12760SJiri Olsa [PERF_COUNT_HW_BRANCH_MISSES] = { 611dc12760SJiri Olsa .symbol = "branch-misses", 621dc12760SJiri Olsa .alias = "", 631dc12760SJiri Olsa }, 641dc12760SJiri Olsa [PERF_COUNT_HW_BUS_CYCLES] = { 651dc12760SJiri Olsa .symbol = "bus-cycles", 661dc12760SJiri Olsa .alias = "", 671dc12760SJiri Olsa }, 681dc12760SJiri Olsa [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = { 691dc12760SJiri Olsa .symbol = "stalled-cycles-frontend", 701dc12760SJiri Olsa .alias = "idle-cycles-frontend", 711dc12760SJiri Olsa }, 721dc12760SJiri Olsa [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = { 731dc12760SJiri Olsa .symbol = "stalled-cycles-backend", 741dc12760SJiri Olsa .alias = "idle-cycles-backend", 751dc12760SJiri Olsa }, 761dc12760SJiri Olsa [PERF_COUNT_HW_REF_CPU_CYCLES] = { 771dc12760SJiri Olsa .symbol = "ref-cycles", 781dc12760SJiri Olsa .alias = "", 791dc12760SJiri Olsa }, 801dc12760SJiri Olsa }; 8186470930SIngo Molnar 824a20e793SIan Rogers const struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = { 831dc12760SJiri Olsa [PERF_COUNT_SW_CPU_CLOCK] = { 841dc12760SJiri Olsa .symbol = "cpu-clock", 851dc12760SJiri Olsa .alias = "", 861dc12760SJiri Olsa }, 871dc12760SJiri Olsa [PERF_COUNT_SW_TASK_CLOCK] = { 881dc12760SJiri Olsa .symbol = "task-clock", 891dc12760SJiri Olsa .alias = "", 901dc12760SJiri Olsa }, 911dc12760SJiri Olsa [PERF_COUNT_SW_PAGE_FAULTS] = { 921dc12760SJiri Olsa .symbol = "page-faults", 931dc12760SJiri Olsa .alias = "faults", 941dc12760SJiri Olsa }, 951dc12760SJiri Olsa [PERF_COUNT_SW_CONTEXT_SWITCHES] = { 961dc12760SJiri Olsa .symbol = "context-switches", 971dc12760SJiri Olsa .alias = "cs", 981dc12760SJiri Olsa }, 991dc12760SJiri Olsa [PERF_COUNT_SW_CPU_MIGRATIONS] = { 1001dc12760SJiri Olsa .symbol = "cpu-migrations", 1011dc12760SJiri Olsa .alias = "migrations", 1021dc12760SJiri Olsa }, 1031dc12760SJiri Olsa [PERF_COUNT_SW_PAGE_FAULTS_MIN] = { 1041dc12760SJiri Olsa .symbol = "minor-faults", 1051dc12760SJiri Olsa .alias = "", 1061dc12760SJiri Olsa }, 1071dc12760SJiri Olsa [PERF_COUNT_SW_PAGE_FAULTS_MAJ] = { 1081dc12760SJiri Olsa .symbol = "major-faults", 1091dc12760SJiri Olsa .alias = "", 1101dc12760SJiri Olsa }, 1111dc12760SJiri Olsa [PERF_COUNT_SW_ALIGNMENT_FAULTS] = { 1121dc12760SJiri Olsa .symbol = "alignment-faults", 1131dc12760SJiri Olsa .alias = "", 1141dc12760SJiri Olsa }, 1151dc12760SJiri Olsa [PERF_COUNT_SW_EMULATION_FAULTS] = { 1161dc12760SJiri Olsa .symbol = "emulation-faults", 1171dc12760SJiri Olsa .alias = "", 1181dc12760SJiri Olsa }, 119d22d1a2aSAdrian Hunter [PERF_COUNT_SW_DUMMY] = { 120d22d1a2aSAdrian Hunter .symbol = "dummy", 121d22d1a2aSAdrian Hunter .alias = "", 122d22d1a2aSAdrian Hunter }, 123bae9cc41SArnaldo Carvalho de Melo [PERF_COUNT_SW_BPF_OUTPUT] = { 124bae9cc41SArnaldo Carvalho de Melo .symbol = "bpf-output", 125bae9cc41SArnaldo Carvalho de Melo .alias = "", 126bae9cc41SArnaldo Carvalho de Melo }, 127fb6c79d7SNamhyung Kim [PERF_COUNT_SW_CGROUP_SWITCHES] = { 128fb6c79d7SNamhyung Kim .symbol = "cgroup-switches", 129fb6c79d7SNamhyung Kim .alias = "", 130fb6c79d7SNamhyung Kim }, 13186470930SIngo Molnar }; 13286470930SIngo Molnar 1331424dc96SDavid Ahern const char *event_type(int type) 1341424dc96SDavid Ahern { 1351424dc96SDavid Ahern switch (type) { 1361424dc96SDavid Ahern case PERF_TYPE_HARDWARE: 1371424dc96SDavid Ahern return "hardware"; 1381424dc96SDavid Ahern 1391424dc96SDavid Ahern case PERF_TYPE_SOFTWARE: 1401424dc96SDavid Ahern return "software"; 1411424dc96SDavid Ahern 1421424dc96SDavid Ahern case PERF_TYPE_TRACEPOINT: 1431424dc96SDavid Ahern return "tracepoint"; 1441424dc96SDavid Ahern 1451424dc96SDavid Ahern case PERF_TYPE_HW_CACHE: 1461424dc96SDavid Ahern return "hardware-cache"; 1471424dc96SDavid Ahern 1481424dc96SDavid Ahern default: 1491424dc96SDavid Ahern break; 1501424dc96SDavid Ahern } 1511424dc96SDavid Ahern 1521424dc96SDavid Ahern return "unknown"; 1531424dc96SDavid Ahern } 1541424dc96SDavid Ahern 1555ccc4edfSIan Rogers static char *get_config_str(const struct parse_events_terms *head_terms, 1560d3f0e6fSIan Rogers enum parse_events__term_type type_term) 157e814fdddSWang Nan { 158e814fdddSWang Nan struct parse_events_term *term; 159e814fdddSWang Nan 160e814fdddSWang Nan if (!head_terms) 161e814fdddSWang Nan return NULL; 162e814fdddSWang Nan 1630d3f0e6fSIan Rogers list_for_each_entry(term, &head_terms->terms, list) 1642b62b3a6SIan Rogers if (term->type_term == type_term) 165e814fdddSWang Nan return term->val.str; 166e814fdddSWang Nan 167e814fdddSWang Nan return NULL; 168e814fdddSWang Nan } 1697ae92e74SYan, Zheng 1705ccc4edfSIan Rogers static char *get_config_metric_id(const struct parse_events_terms *head_terms) 1712b62b3a6SIan Rogers { 1722b62b3a6SIan Rogers return get_config_str(head_terms, PARSE_EVENTS__TERM_TYPE_METRIC_ID); 1732b62b3a6SIan Rogers } 1742b62b3a6SIan Rogers 1755ccc4edfSIan Rogers static char *get_config_name(const struct parse_events_terms *head_terms) 1762b62b3a6SIan Rogers { 1772b62b3a6SIan Rogers return get_config_str(head_terms, PARSE_EVENTS__TERM_TYPE_NAME); 1782b62b3a6SIan Rogers } 1792b62b3a6SIan Rogers 18070c90e4aSIan Rogers /** 18170c90e4aSIan Rogers * fix_raw - For each raw term see if there is an event (aka alias) in pmu that 18270c90e4aSIan Rogers * matches the raw's string value. If the string value matches an 18370c90e4aSIan Rogers * event then change the term to be an event, if not then change it to 18470c90e4aSIan Rogers * be a config term. For example, "read" may be an event of the PMU or 18570c90e4aSIan Rogers * a raw hex encoding of 0xead. The fix-up is done late so the PMU of 18670c90e4aSIan Rogers * the event can be determined and we don't need to scan all PMUs 18770c90e4aSIan Rogers * ahead-of-time. 18870c90e4aSIan Rogers * @config_terms: the list of terms that may contain a raw term. 18970c90e4aSIan Rogers * @pmu: the PMU to scan for events from. 19070c90e4aSIan Rogers */ 1910d3f0e6fSIan Rogers static void fix_raw(struct parse_events_terms *config_terms, struct perf_pmu *pmu) 19270c90e4aSIan Rogers { 19370c90e4aSIan Rogers struct parse_events_term *term; 19470c90e4aSIan Rogers 1950d3f0e6fSIan Rogers list_for_each_entry(term, &config_terms->terms, list) { 196c3245d20SIan Rogers u64 num; 19770c90e4aSIan Rogers 19870c90e4aSIan Rogers if (term->type_term != PARSE_EVENTS__TERM_TYPE_RAW) 19970c90e4aSIan Rogers continue; 20070c90e4aSIan Rogers 201c3245d20SIan Rogers if (perf_pmu__have_event(pmu, term->val.str)) { 202970ef02eSIan Rogers zfree(&term->config); 20370c90e4aSIan Rogers term->config = term->val.str; 20470c90e4aSIan Rogers term->type_val = PARSE_EVENTS__TERM_TYPE_NUM; 20570c90e4aSIan Rogers term->type_term = PARSE_EVENTS__TERM_TYPE_USER; 20670c90e4aSIan Rogers term->val.num = 1; 20770c90e4aSIan Rogers term->no_value = true; 208c3245d20SIan Rogers continue; 20970c90e4aSIan Rogers } 21070c90e4aSIan Rogers 211970ef02eSIan Rogers zfree(&term->config); 21270c90e4aSIan Rogers term->config = strdup("config"); 21370c90e4aSIan Rogers errno = 0; 21470c90e4aSIan Rogers num = strtoull(term->val.str + 1, NULL, 16); 21570c90e4aSIan Rogers assert(errno == 0); 21670c90e4aSIan Rogers free(term->val.str); 21770c90e4aSIan Rogers term->type_val = PARSE_EVENTS__TERM_TYPE_NUM; 21870c90e4aSIan Rogers term->type_term = PARSE_EVENTS__TERM_TYPE_CONFIG; 21970c90e4aSIan Rogers term->val.num = num; 22070c90e4aSIan Rogers term->no_value = false; 22170c90e4aSIan Rogers } 22270c90e4aSIan Rogers } 22370c90e4aSIan Rogers 22432dcd021SJiri Olsa static struct evsel * 225410136f5SStephane Eranian __add_event(struct list_head *list, int *idx, 2267ae92e74SYan, Zheng struct perf_event_attr *attr, 22770943490SStephane Eranian bool init_attr, 2282b62b3a6SIan Rogers const char *name, const char *metric_id, struct perf_pmu *pmu, 229f0fbb114SAndi Kleen struct list_head *config_terms, bool auto_merge_stats, 230f0fbb114SAndi Kleen const char *cpu_list) 23189812fc8SJiri Olsa { 23232dcd021SJiri Olsa struct evsel *evsel; 2335d680be3SNamhyung Kim struct perf_cpu_map *cpus = pmu ? perf_cpu_map__get(pmu->cpus) : 2349c3516d1SJiri Olsa cpu_list ? perf_cpu_map__new(cpu_list) : NULL; 23589812fc8SJiri Olsa 236e552b7beSRob Herring if (pmu) 237e552b7beSRob Herring perf_pmu__warn_invalid_formats(pmu); 238e552b7beSRob Herring 239b9f01032SIan Rogers if (pmu && (attr->type == PERF_TYPE_RAW || attr->type >= PERF_TYPE_MAX)) { 240b9f01032SIan Rogers perf_pmu__warn_invalid_config(pmu, attr->config, name, 241b9f01032SIan Rogers PERF_PMU_FORMAT_VALUE_CONFIG, "config"); 242b9f01032SIan Rogers perf_pmu__warn_invalid_config(pmu, attr->config1, name, 243b9f01032SIan Rogers PERF_PMU_FORMAT_VALUE_CONFIG1, "config1"); 244b9f01032SIan Rogers perf_pmu__warn_invalid_config(pmu, attr->config2, name, 245b9f01032SIan Rogers PERF_PMU_FORMAT_VALUE_CONFIG2, "config2"); 246b9f01032SIan Rogers perf_pmu__warn_invalid_config(pmu, attr->config3, name, 247b9f01032SIan Rogers PERF_PMU_FORMAT_VALUE_CONFIG3, "config3"); 248b9f01032SIan Rogers } 24970943490SStephane Eranian if (init_attr) 25089812fc8SJiri Olsa event_attr_init(attr); 25189812fc8SJiri Olsa 2528f6725a2SArnaldo Carvalho de Melo evsel = evsel__new_idx(attr, *idx); 2530f1b550eSNamhyung Kim if (!evsel) { 2540f1b550eSNamhyung Kim perf_cpu_map__put(cpus); 255410136f5SStephane Eranian return NULL; 2560f1b550eSNamhyung Kim } 25789812fc8SJiri Olsa 25875fc5ae5STaeung Song (*idx)++; 2595d680be3SNamhyung Kim evsel->core.cpus = cpus; 260fe1f61b3SJiri Olsa evsel->core.own_cpus = perf_cpu_map__get(cpus); 261d3345fecSAdrian Hunter evsel->core.requires_cpu = pmu ? pmu->is_uncore : false; 2621578e63dSIan Rogers evsel->core.is_pmu_core = pmu ? pmu->is_core : false; 26363ce8449SArnaldo Carvalho de Melo evsel->auto_merge_stats = auto_merge_stats; 264f7400262SNamhyung Kim evsel->pmu = pmu; 265c091ee90SIan Rogers evsel->pmu_name = pmu ? strdup(pmu->name) : NULL; 266f30a79b0SJiri Olsa 2679db1763cSArnaldo Carvalho de Melo if (name) 26889812fc8SJiri Olsa evsel->name = strdup(name); 269930a2e29SJiri Olsa 2702b62b3a6SIan Rogers if (metric_id) 2712b62b3a6SIan Rogers evsel->metric_id = strdup(metric_id); 2722b62b3a6SIan Rogers 273930a2e29SJiri Olsa if (config_terms) 27499fc5941SAdrian Hunter list_splice_init(config_terms, &evsel->config_terms); 275930a2e29SJiri Olsa 27670943490SStephane Eranian if (list) 277b27c4eceSJiri Olsa list_add_tail(&evsel->core.node, list); 27870943490SStephane Eranian 279410136f5SStephane Eranian return evsel; 28089812fc8SJiri Olsa } 28189812fc8SJiri Olsa 28270943490SStephane Eranian struct evsel *parse_events__add_event(int idx, struct perf_event_attr *attr, 2832b62b3a6SIan Rogers const char *name, const char *metric_id, 2842b62b3a6SIan Rogers struct perf_pmu *pmu) 28570943490SStephane Eranian { 2862b62b3a6SIan Rogers return __add_event(/*list=*/NULL, &idx, attr, /*init_attr=*/false, name, 2872b62b3a6SIan Rogers metric_id, pmu, /*config_terms=*/NULL, 2882b62b3a6SIan Rogers /*auto_merge_stats=*/false, /*cpu_list=*/NULL); 28970943490SStephane Eranian } 29070943490SStephane Eranian 291c5cd8ac0SDavid Ahern static int add_event(struct list_head *list, int *idx, 2928e8bbfb3SIan Rogers struct perf_event_attr *attr, const char *name, 2932b62b3a6SIan Rogers const char *metric_id, struct list_head *config_terms) 2947ae92e74SYan, Zheng { 2952b62b3a6SIan Rogers return __add_event(list, idx, attr, /*init_attr*/true, name, metric_id, 2962b62b3a6SIan Rogers /*pmu=*/NULL, config_terms, 2972b62b3a6SIan Rogers /*auto_merge_stats=*/false, /*cpu_list=*/NULL) ? 0 : -ENOMEM; 298f0fbb114SAndi Kleen } 299f0fbb114SAndi Kleen 300f0fbb114SAndi Kleen static int add_event_tool(struct list_head *list, int *idx, 301f0fbb114SAndi Kleen enum perf_tool_event tool_event) 302f0fbb114SAndi Kleen { 30332dcd021SJiri Olsa struct evsel *evsel; 304f0fbb114SAndi Kleen struct perf_event_attr attr = { 305f0fbb114SAndi Kleen .type = PERF_TYPE_SOFTWARE, 306f0fbb114SAndi Kleen .config = PERF_COUNT_SW_DUMMY, 307f0fbb114SAndi Kleen }; 308*6828d692SIan Rogers const char *cpu_list = NULL; 309f0fbb114SAndi Kleen 310*6828d692SIan Rogers if (tool_event == PERF_TOOL_DURATION_TIME) { 311*6828d692SIan Rogers /* Duration time is gathered globally, pretend it is only on CPU0. */ 312*6828d692SIan Rogers cpu_list = "0"; 313*6828d692SIan Rogers } 3142b62b3a6SIan Rogers evsel = __add_event(list, idx, &attr, /*init_attr=*/true, /*name=*/NULL, 3152b62b3a6SIan Rogers /*metric_id=*/NULL, /*pmu=*/NULL, 3162b62b3a6SIan Rogers /*config_terms=*/NULL, /*auto_merge_stats=*/false, 317*6828d692SIan Rogers cpu_list); 318f0fbb114SAndi Kleen if (!evsel) 319f0fbb114SAndi Kleen return -ENOMEM; 320f0fbb114SAndi Kleen evsel->tool_event = tool_event; 321b03b89b3SFlorian Fischer if (tool_event == PERF_TOOL_DURATION_TIME 322b03b89b3SFlorian Fischer || tool_event == PERF_TOOL_USER_TIME 323b03b89b3SFlorian Fischer || tool_event == PERF_TOOL_SYSTEM_TIME) { 324b194c9cdSIan Rogers free((char *)evsel->unit); 325b194c9cdSIan Rogers evsel->unit = strdup("ns"); 326b194c9cdSIan Rogers } 327f0fbb114SAndi Kleen return 0; 3287ae92e74SYan, Zheng } 3297ae92e74SYan, Zheng 33070c90e4aSIan Rogers /** 33170c90e4aSIan Rogers * parse_aliases - search names for entries beginning or equalling str ignoring 33270c90e4aSIan Rogers * case. If mutliple entries in names match str then the longest 33370c90e4aSIan Rogers * is chosen. 33470c90e4aSIan Rogers * @str: The needle to look for. 33570c90e4aSIan Rogers * @names: The haystack to search. 33670c90e4aSIan Rogers * @size: The size of the haystack. 33770c90e4aSIan Rogers * @longest: Out argument giving the length of the matching entry. 33870c90e4aSIan Rogers */ 33970c90e4aSIan Rogers static int parse_aliases(const char *str, const char *const names[][EVSEL__MAX_ALIASES], int size, 34070c90e4aSIan Rogers int *longest) 34186470930SIngo Molnar { 34270c90e4aSIan Rogers *longest = -1; 34370c90e4aSIan Rogers for (int i = 0; i < size; i++) { 34470c90e4aSIan Rogers for (int j = 0; j < EVSEL__MAX_ALIASES && names[i][j]; j++) { 34570c90e4aSIan Rogers int n = strlen(names[i][j]); 34686470930SIngo Molnar 34770c90e4aSIan Rogers if (n > *longest && !strncasecmp(str, names[i][j], n)) 34870c90e4aSIan Rogers *longest = n; 34961c45981SPaul Mackerras } 35070c90e4aSIan Rogers if (*longest > 0) 35186470930SIngo Molnar return i; 35286470930SIngo Molnar } 35386470930SIngo Molnar 3548953645fSIngo Molnar return -1; 35586470930SIngo Molnar } 35686470930SIngo Molnar 35743d0b978SWang Nan typedef int config_term_func_t(struct perf_event_attr *attr, 35843d0b978SWang Nan struct parse_events_term *term, 35943d0b978SWang Nan struct parse_events_error *err); 36043d0b978SWang Nan static int config_term_common(struct perf_event_attr *attr, 36143d0b978SWang Nan struct parse_events_term *term, 36243d0b978SWang Nan struct parse_events_error *err); 36343d0b978SWang Nan static int config_attr(struct perf_event_attr *attr, 3645ccc4edfSIan Rogers const struct parse_events_terms *head, 36543d0b978SWang Nan struct parse_events_error *err, 36643d0b978SWang Nan config_term_func_t config_term); 36743d0b978SWang Nan 3686fd1e519SIan Rogers /** 3696fd1e519SIan Rogers * parse_events__decode_legacy_cache - Search name for the legacy cache event 3706fd1e519SIan Rogers * name composed of 1, 2 or 3 hyphen 3716fd1e519SIan Rogers * separated sections. The first section is 3726fd1e519SIan Rogers * the cache type while the others are the 3736fd1e519SIan Rogers * optional op and optional result. To make 3746fd1e519SIan Rogers * life hard the names in the table also 3756fd1e519SIan Rogers * contain hyphens and the longest name 37670c90e4aSIan Rogers * should always be selected. 37786470930SIngo Molnar */ 378251aa040SIan Rogers int parse_events__decode_legacy_cache(const char *name, int extended_pmu_type, __u64 *config) 3796fd1e519SIan Rogers { 3806fd1e519SIan Rogers int len, cache_type = -1, cache_op = -1, cache_result = -1; 3816fd1e519SIan Rogers const char *name_end = &name[strlen(name) + 1]; 3826fd1e519SIan Rogers const char *str = name; 3836fd1e519SIan Rogers 38470c90e4aSIan Rogers cache_type = parse_aliases(str, evsel__hw_cache, PERF_COUNT_HW_CACHE_MAX, &len); 38586470930SIngo Molnar if (cache_type == -1) 38689812fc8SJiri Olsa return -EINVAL; 38770c90e4aSIan Rogers str += len + 1; 38886470930SIngo Molnar 38970c90e4aSIan Rogers if (str < name_end) { 390c64e85e1SArnaldo Carvalho de Melo cache_op = parse_aliases(str, evsel__hw_cache_op, 39170c90e4aSIan Rogers PERF_COUNT_HW_CACHE_OP_MAX, &len); 39261c45981SPaul Mackerras if (cache_op >= 0) { 393c754c382SArnaldo Carvalho de Melo if (!evsel__is_cache_op_valid(cache_type, cache_op)) 39489812fc8SJiri Olsa return -EINVAL; 39570c90e4aSIan Rogers str += len + 1; 39670c90e4aSIan Rogers } else { 397c64e85e1SArnaldo Carvalho de Melo cache_result = parse_aliases(str, evsel__hw_cache_result, 39870c90e4aSIan Rogers PERF_COUNT_HW_CACHE_RESULT_MAX, &len); 39961c45981SPaul Mackerras if (cache_result >= 0) 40070c90e4aSIan Rogers str += len + 1; 40170c90e4aSIan Rogers } 40270c90e4aSIan Rogers } 40370c90e4aSIan Rogers if (str < name_end) { 40470c90e4aSIan Rogers if (cache_op < 0) { 40570c90e4aSIan Rogers cache_op = parse_aliases(str, evsel__hw_cache_op, 40670c90e4aSIan Rogers PERF_COUNT_HW_CACHE_OP_MAX, &len); 40770c90e4aSIan Rogers if (cache_op >= 0) { 40870c90e4aSIan Rogers if (!evsel__is_cache_op_valid(cache_type, cache_op)) 40970c90e4aSIan Rogers return -EINVAL; 41070c90e4aSIan Rogers } 41170c90e4aSIan Rogers } else if (cache_result < 0) { 41270c90e4aSIan Rogers cache_result = parse_aliases(str, evsel__hw_cache_result, 41370c90e4aSIan Rogers PERF_COUNT_HW_CACHE_RESULT_MAX, &len); 41461c45981SPaul Mackerras } 41561c45981SPaul Mackerras } 41661c45981SPaul Mackerras 41786470930SIngo Molnar /* 41886470930SIngo Molnar * Fall back to reads: 41986470930SIngo Molnar */ 4208953645fSIngo Molnar if (cache_op == -1) 4218953645fSIngo Molnar cache_op = PERF_COUNT_HW_CACHE_OP_READ; 42286470930SIngo Molnar 42386470930SIngo Molnar /* 42486470930SIngo Molnar * Fall back to accesses: 42586470930SIngo Molnar */ 42686470930SIngo Molnar if (cache_result == -1) 42786470930SIngo Molnar cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS; 42886470930SIngo Molnar 429251aa040SIan Rogers *config = cache_type | (cache_op << 8) | (cache_result << 16); 430251aa040SIan Rogers if (perf_pmus__supports_extended_type()) 431251aa040SIan Rogers *config |= (__u64)extended_pmu_type << PERF_PMU_TYPE_SHIFT; 4326fd1e519SIan Rogers return 0; 4336fd1e519SIan Rogers } 4346fd1e519SIan Rogers 435411ad22eSIan Rogers /** 436411ad22eSIan Rogers * parse_events__filter_pmu - returns false if a wildcard PMU should be 437411ad22eSIan Rogers * considered, true if it should be filtered. 438411ad22eSIan Rogers */ 439411ad22eSIan Rogers bool parse_events__filter_pmu(const struct parse_events_state *parse_state, 440411ad22eSIan Rogers const struct perf_pmu *pmu) 441411ad22eSIan Rogers { 442411ad22eSIan Rogers if (parse_state->pmu_filter == NULL) 443411ad22eSIan Rogers return false; 444411ad22eSIan Rogers 445411ad22eSIan Rogers return strcmp(parse_state->pmu_filter, pmu->name) != 0; 446411ad22eSIan Rogers } 447411ad22eSIan Rogers 44862593394SIan Rogers static int parse_events_add_pmu(struct parse_events_state *parse_state, 44962593394SIan Rogers struct list_head *list, struct perf_pmu *pmu, 45062593394SIan Rogers const struct parse_events_terms *const_parsed_terms, 45162593394SIan Rogers bool auto_merge_stats); 45262593394SIan Rogers 4536fd1e519SIan Rogers int parse_events_add_cache(struct list_head *list, int *idx, const char *name, 454411ad22eSIan Rogers struct parse_events_state *parse_state, 45562593394SIan Rogers struct parse_events_terms *parsed_terms) 4566fd1e519SIan Rogers { 4572bdf4d7eSIan Rogers struct perf_pmu *pmu = NULL; 4582bdf4d7eSIan Rogers bool found_supported = false; 45962593394SIan Rogers const char *config_name = get_config_name(parsed_terms); 46062593394SIan Rogers const char *metric_id = get_config_metric_id(parsed_terms); 4616fd1e519SIan Rogers 46262593394SIan Rogers while ((pmu = perf_pmus__scan(pmu)) != NULL) { 4632bdf4d7eSIan Rogers LIST_HEAD(config_terms); 4642bdf4d7eSIan Rogers struct perf_event_attr attr; 4652bdf4d7eSIan Rogers int ret; 4662bdf4d7eSIan Rogers 467411ad22eSIan Rogers if (parse_events__filter_pmu(parse_state, pmu)) 468411ad22eSIan Rogers continue; 469411ad22eSIan Rogers 47062593394SIan Rogers if (perf_pmu__have_event(pmu, name)) { 47162593394SIan Rogers /* 47262593394SIan Rogers * The PMU has the event so add as not a legacy cache 47362593394SIan Rogers * event. 47462593394SIan Rogers */ 47562593394SIan Rogers ret = parse_events_add_pmu(parse_state, list, pmu, 47662593394SIan Rogers parsed_terms, 47762593394SIan Rogers perf_pmu__auto_merge_stats(pmu)); 47862593394SIan Rogers if (ret) 47962593394SIan Rogers return ret; 48062593394SIan Rogers continue; 48162593394SIan Rogers } 48262593394SIan Rogers 48362593394SIan Rogers if (!pmu->is_core) { 48462593394SIan Rogers /* Legacy cache events are only supported by core PMUs. */ 48562593394SIan Rogers continue; 48662593394SIan Rogers } 48762593394SIan Rogers 48889812fc8SJiri Olsa memset(&attr, 0, sizeof(attr)); 48989812fc8SJiri Olsa attr.type = PERF_TYPE_HW_CACHE; 4902bdf4d7eSIan Rogers 4912bdf4d7eSIan Rogers ret = parse_events__decode_legacy_cache(name, pmu->type, &attr.config); 4926fd1e519SIan Rogers if (ret) 4936fd1e519SIan Rogers return ret; 49443d0b978SWang Nan 4952bdf4d7eSIan Rogers found_supported = true; 4962bdf4d7eSIan Rogers 49762593394SIan Rogers if (parsed_terms) { 49862593394SIan Rogers if (config_attr(&attr, parsed_terms, parse_state->error, 49962593394SIan Rogers config_term_common)) 50043d0b978SWang Nan return -EINVAL; 50143d0b978SWang Nan 50262593394SIan Rogers if (get_config_terms(parsed_terms, &config_terms)) 50343d0b978SWang Nan return -ENOMEM; 50443d0b978SWang Nan } 50530def61fSJin Yao 5062bdf4d7eSIan Rogers if (__add_event(list, idx, &attr, /*init_attr*/true, config_name ?: name, 5072bdf4d7eSIan Rogers metric_id, pmu, &config_terms, /*auto_merge_stats=*/false, 5082bdf4d7eSIan Rogers /*cpu_list=*/NULL) == NULL) 5092bdf4d7eSIan Rogers return -ENOMEM; 51030def61fSJin Yao 51199fc5941SAdrian Hunter free_config_terms(&config_terms); 5122bdf4d7eSIan Rogers } 5132bdf4d7eSIan Rogers return found_supported ? 0 : -EINVAL; 51486470930SIngo Molnar } 51586470930SIngo Molnar 516378ef0f5SIan Rogers #ifdef HAVE_LIBTRACEEVENT 517272ed29aSJiri Olsa static void tracepoint_error(struct parse_events_error *e, int err, 518d81fa63bSIan Rogers const char *sys, const char *name, int column) 51919658171SJiri Olsa { 5204584f084SIan Rogers const char *str; 52119658171SJiri Olsa char help[BUFSIZ]; 52219658171SJiri Olsa 523ec183d22SAdrian Hunter if (!e) 524ec183d22SAdrian Hunter return; 525ec183d22SAdrian Hunter 52619658171SJiri Olsa /* 52719658171SJiri Olsa * We get error directly from syscall errno ( > 0), 52819658171SJiri Olsa * or from encoded pointer's error ( < 0). 52919658171SJiri Olsa */ 53019658171SJiri Olsa err = abs(err); 53119658171SJiri Olsa 53219658171SJiri Olsa switch (err) { 53319658171SJiri Olsa case EACCES: 5344584f084SIan Rogers str = "can't access trace events"; 53519658171SJiri Olsa break; 53619658171SJiri Olsa case ENOENT: 5374584f084SIan Rogers str = "unknown tracepoint"; 53819658171SJiri Olsa break; 53919658171SJiri Olsa default: 5404584f084SIan Rogers str = "failed to add tracepoint"; 54119658171SJiri Olsa break; 54219658171SJiri Olsa } 54319658171SJiri Olsa 54419658171SJiri Olsa tracing_path__strerror_open_tp(err, help, sizeof(help), sys, name); 545d81fa63bSIan Rogers parse_events_error__handle(e, column, strdup(str), strdup(help)); 54619658171SJiri Olsa } 54719658171SJiri Olsa 54811a42964SDominique Martinet static int add_tracepoint(struct parse_events_state *parse_state, 54911a42964SDominique Martinet struct list_head *list, 5508c619d6aSWang Nan const char *sys_name, const char *evt_name, 551272ed29aSJiri Olsa struct parse_events_error *err, 5520d3f0e6fSIan Rogers struct parse_events_terms *head_config, void *loc_) 553bcd3279fSFrederic Weisbecker { 554d81fa63bSIan Rogers YYLTYPE *loc = loc_; 555a2a6604eSDominique Martinet struct evsel *evsel = evsel__newtp_idx(sys_name, evt_name, parse_state->idx++, 556a2a6604eSDominique Martinet !parse_state->fake_tp); 557bcd3279fSFrederic Weisbecker 55819658171SJiri Olsa if (IS_ERR(evsel)) { 559d81fa63bSIan Rogers tracepoint_error(err, PTR_ERR(evsel), sys_name, evt_name, loc->first_column); 5608dd2a131SJiri Olsa return PTR_ERR(evsel); 56119658171SJiri Olsa } 562bcd3279fSFrederic Weisbecker 563e637d177SHe Kuang if (head_config) { 564e637d177SHe Kuang LIST_HEAD(config_terms); 565e637d177SHe Kuang 566e637d177SHe Kuang if (get_config_terms(head_config, &config_terms)) 567e637d177SHe Kuang return -ENOMEM; 568e637d177SHe Kuang list_splice(&config_terms, &evsel->config_terms); 569e637d177SHe Kuang } 570e637d177SHe Kuang 571b27c4eceSJiri Olsa list_add_tail(&evsel->core.node, list); 57282fe1c29SArnaldo Carvalho de Melo return 0; 573bcd3279fSFrederic Weisbecker } 574bcd3279fSFrederic Weisbecker 57511a42964SDominique Martinet static int add_tracepoint_multi_event(struct parse_events_state *parse_state, 57611a42964SDominique Martinet struct list_head *list, 5778c619d6aSWang Nan const char *sys_name, const char *evt_name, 578272ed29aSJiri Olsa struct parse_events_error *err, 5790d3f0e6fSIan Rogers struct parse_events_terms *head_config, YYLTYPE *loc) 580bcd3279fSFrederic Weisbecker { 58125a7d914SArnaldo Carvalho de Melo char *evt_path; 582bcd3279fSFrederic Weisbecker struct dirent *evt_ent; 583bcd3279fSFrederic Weisbecker DIR *evt_dir; 58427bf90bfSJiri Olsa int ret = 0, found = 0; 585bcd3279fSFrederic Weisbecker 58625a7d914SArnaldo Carvalho de Melo evt_path = get_events_file(sys_name); 58725a7d914SArnaldo Carvalho de Melo if (!evt_path) { 588d81fa63bSIan Rogers tracepoint_error(err, errno, sys_name, evt_name, loc->first_column); 58925a7d914SArnaldo Carvalho de Melo return -1; 59025a7d914SArnaldo Carvalho de Melo } 591bcd3279fSFrederic Weisbecker evt_dir = opendir(evt_path); 592bcd3279fSFrederic Weisbecker if (!evt_dir) { 59325a7d914SArnaldo Carvalho de Melo put_events_file(evt_path); 594d81fa63bSIan Rogers tracepoint_error(err, errno, sys_name, evt_name, loc->first_column); 59589812fc8SJiri Olsa return -1; 596bcd3279fSFrederic Weisbecker } 597bcd3279fSFrederic Weisbecker 59889812fc8SJiri Olsa while (!ret && (evt_ent = readdir(evt_dir))) { 599bcd3279fSFrederic Weisbecker if (!strcmp(evt_ent->d_name, ".") 600bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "..") 601bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "enable") 602bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "filter")) 603bcd3279fSFrederic Weisbecker continue; 604bcd3279fSFrederic Weisbecker 60589812fc8SJiri Olsa if (!strglobmatch(evt_ent->d_name, evt_name)) 606fb1d2edfSMasami Hiramatsu continue; 607fb1d2edfSMasami Hiramatsu 60827bf90bfSJiri Olsa found++; 60927bf90bfSJiri Olsa 61011a42964SDominique Martinet ret = add_tracepoint(parse_state, list, sys_name, evt_ent->d_name, 611d81fa63bSIan Rogers err, head_config, loc); 612bcd3279fSFrederic Weisbecker } 613bcd3279fSFrederic Weisbecker 61427bf90bfSJiri Olsa if (!found) { 615d81fa63bSIan Rogers tracepoint_error(err, ENOENT, sys_name, evt_name, loc->first_column); 61627bf90bfSJiri Olsa ret = -1; 61727bf90bfSJiri Olsa } 61827bf90bfSJiri Olsa 61925a7d914SArnaldo Carvalho de Melo put_events_file(evt_path); 6200bd3f084SJiri Olsa closedir(evt_dir); 62189812fc8SJiri Olsa return ret; 622bcd3279fSFrederic Weisbecker } 623bcd3279fSFrederic Weisbecker 62411a42964SDominique Martinet static int add_tracepoint_event(struct parse_events_state *parse_state, 62511a42964SDominique Martinet struct list_head *list, 6268c619d6aSWang Nan const char *sys_name, const char *evt_name, 627272ed29aSJiri Olsa struct parse_events_error *err, 6280d3f0e6fSIan Rogers struct parse_events_terms *head_config, YYLTYPE *loc) 629f35488f9SJiri Olsa { 630f35488f9SJiri Olsa return strpbrk(evt_name, "*?") ? 63111a42964SDominique Martinet add_tracepoint_multi_event(parse_state, list, sys_name, evt_name, 632d81fa63bSIan Rogers err, head_config, loc) : 63311a42964SDominique Martinet add_tracepoint(parse_state, list, sys_name, evt_name, 634d81fa63bSIan Rogers err, head_config, loc); 635f35488f9SJiri Olsa } 636f35488f9SJiri Olsa 63711a42964SDominique Martinet static int add_tracepoint_multi_sys(struct parse_events_state *parse_state, 63811a42964SDominique Martinet struct list_head *list, 6398c619d6aSWang Nan const char *sys_name, const char *evt_name, 640272ed29aSJiri Olsa struct parse_events_error *err, 6410d3f0e6fSIan Rogers struct parse_events_terms *head_config, YYLTYPE *loc) 642f35488f9SJiri Olsa { 643f35488f9SJiri Olsa struct dirent *events_ent; 644f35488f9SJiri Olsa DIR *events_dir; 645f35488f9SJiri Olsa int ret = 0; 646f35488f9SJiri Olsa 6477014e0e3SArnaldo Carvalho de Melo events_dir = tracing_events__opendir(); 648f35488f9SJiri Olsa if (!events_dir) { 649d81fa63bSIan Rogers tracepoint_error(err, errno, sys_name, evt_name, loc->first_column); 650f35488f9SJiri Olsa return -1; 651f35488f9SJiri Olsa } 652f35488f9SJiri Olsa 653f35488f9SJiri Olsa while (!ret && (events_ent = readdir(events_dir))) { 654f35488f9SJiri Olsa if (!strcmp(events_ent->d_name, ".") 655f35488f9SJiri Olsa || !strcmp(events_ent->d_name, "..") 656f35488f9SJiri Olsa || !strcmp(events_ent->d_name, "enable") 657f35488f9SJiri Olsa || !strcmp(events_ent->d_name, "header_event") 658f35488f9SJiri Olsa || !strcmp(events_ent->d_name, "header_page")) 659f35488f9SJiri Olsa continue; 660f35488f9SJiri Olsa 661f35488f9SJiri Olsa if (!strglobmatch(events_ent->d_name, sys_name)) 662f35488f9SJiri Olsa continue; 663f35488f9SJiri Olsa 66411a42964SDominique Martinet ret = add_tracepoint_event(parse_state, list, events_ent->d_name, 665d81fa63bSIan Rogers evt_name, err, head_config, loc); 666f35488f9SJiri Olsa } 667f35488f9SJiri Olsa 668f35488f9SJiri Olsa closedir(events_dir); 669f35488f9SJiri Olsa return ret; 670f35488f9SJiri Olsa } 671378ef0f5SIan Rogers #endif /* HAVE_LIBTRACEEVENT */ 672f35488f9SJiri Olsa 67389812fc8SJiri Olsa static int 67489812fc8SJiri Olsa parse_breakpoint_type(const char *type, struct perf_event_attr *attr) 6751b290d67SFrederic Weisbecker { 6761b290d67SFrederic Weisbecker int i; 6771b290d67SFrederic Weisbecker 6781b290d67SFrederic Weisbecker for (i = 0; i < 3; i++) { 67989812fc8SJiri Olsa if (!type || !type[i]) 6801b290d67SFrederic Weisbecker break; 6811b290d67SFrederic Weisbecker 6827582732fSJiri Olsa #define CHECK_SET_TYPE(bit) \ 6837582732fSJiri Olsa do { \ 6847582732fSJiri Olsa if (attr->bp_type & bit) \ 6857582732fSJiri Olsa return -EINVAL; \ 6867582732fSJiri Olsa else \ 6877582732fSJiri Olsa attr->bp_type |= bit; \ 6887582732fSJiri Olsa } while (0) 6897582732fSJiri Olsa 6901b290d67SFrederic Weisbecker switch (type[i]) { 6911b290d67SFrederic Weisbecker case 'r': 6927582732fSJiri Olsa CHECK_SET_TYPE(HW_BREAKPOINT_R); 6931b290d67SFrederic Weisbecker break; 6941b290d67SFrederic Weisbecker case 'w': 6957582732fSJiri Olsa CHECK_SET_TYPE(HW_BREAKPOINT_W); 6961b290d67SFrederic Weisbecker break; 6971b290d67SFrederic Weisbecker case 'x': 6987582732fSJiri Olsa CHECK_SET_TYPE(HW_BREAKPOINT_X); 6991b290d67SFrederic Weisbecker break; 7001b290d67SFrederic Weisbecker default: 70189812fc8SJiri Olsa return -EINVAL; 7021b290d67SFrederic Weisbecker } 7031b290d67SFrederic Weisbecker } 70489812fc8SJiri Olsa 7057582732fSJiri Olsa #undef CHECK_SET_TYPE 7067582732fSJiri Olsa 7071b290d67SFrederic Weisbecker if (!attr->bp_type) /* Default */ 7081b290d67SFrederic Weisbecker attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W; 7091b290d67SFrederic Weisbecker 71089812fc8SJiri Olsa return 0; 7111b290d67SFrederic Weisbecker } 7121b290d67SFrederic Weisbecker 713f0617f52SAdrian Hunter int parse_events_add_breakpoint(struct parse_events_state *parse_state, 714f0617f52SAdrian Hunter struct list_head *list, 715f0617f52SAdrian Hunter u64 addr, char *type, u64 len, 7160d3f0e6fSIan Rogers struct parse_events_terms *head_config) 7171b290d67SFrederic Weisbecker { 71889812fc8SJiri Olsa struct perf_event_attr attr; 719f0617f52SAdrian Hunter LIST_HEAD(config_terms); 720f0617f52SAdrian Hunter const char *name; 7211b290d67SFrederic Weisbecker 72289812fc8SJiri Olsa memset(&attr, 0, sizeof(attr)); 723aa98d848SIan Rogers attr.bp_addr = addr; 7241b290d67SFrederic Weisbecker 72589812fc8SJiri Olsa if (parse_breakpoint_type(type, &attr)) 72689812fc8SJiri Olsa return -EINVAL; 7271b290d67SFrederic Weisbecker 7283741eb9fSJacob Shin /* Provide some defaults if len is not specified */ 7293741eb9fSJacob Shin if (!len) { 73089812fc8SJiri Olsa if (attr.bp_type == HW_BREAKPOINT_X) 7313741eb9fSJacob Shin len = sizeof(long); 732aa59a485SFrederic Weisbecker else 7333741eb9fSJacob Shin len = HW_BREAKPOINT_LEN_4; 7343741eb9fSJacob Shin } 7353741eb9fSJacob Shin 7363741eb9fSJacob Shin attr.bp_len = len; 737aa59a485SFrederic Weisbecker 73889812fc8SJiri Olsa attr.type = PERF_TYPE_BREAKPOINT; 7394a841d65SJovi Zhang attr.sample_period = 1; 7401b290d67SFrederic Weisbecker 741f0617f52SAdrian Hunter if (head_config) { 742f0617f52SAdrian Hunter if (config_attr(&attr, head_config, parse_state->error, 743f0617f52SAdrian Hunter config_term_common)) 744f0617f52SAdrian Hunter return -EINVAL; 745f0617f52SAdrian Hunter 746f0617f52SAdrian Hunter if (get_config_terms(head_config, &config_terms)) 747f0617f52SAdrian Hunter return -ENOMEM; 748f0617f52SAdrian Hunter } 749f0617f52SAdrian Hunter 750f0617f52SAdrian Hunter name = get_config_name(head_config); 751f0617f52SAdrian Hunter 752f0617f52SAdrian Hunter return add_event(list, &parse_state->idx, &attr, name, /*mertic_id=*/NULL, 753f0617f52SAdrian Hunter &config_terms); 7541b290d67SFrederic Weisbecker } 7551b290d67SFrederic Weisbecker 7563b0e371cSJiri Olsa static int check_type_val(struct parse_events_term *term, 7573b0e371cSJiri Olsa struct parse_events_error *err, 75858d3a4ceSIan Rogers enum parse_events__term_val_type type) 7593b0e371cSJiri Olsa { 7603b0e371cSJiri Olsa if (type == term->type_val) 7613b0e371cSJiri Olsa return 0; 7623b0e371cSJiri Olsa 7633b0e371cSJiri Olsa if (err) { 7646c191289SIan Rogers parse_events_error__handle(err, term->err_val, 765448d732cSIan Rogers type == PARSE_EVENTS__TERM_TYPE_NUM 766448d732cSIan Rogers ? strdup("expected numeric value") 767448d732cSIan Rogers : strdup("expected string value"), 768448d732cSIan Rogers NULL); 7693b0e371cSJiri Olsa } 7703b0e371cSJiri Olsa return -EINVAL; 7713b0e371cSJiri Olsa } 7723b0e371cSJiri Olsa 77358d3a4ceSIan Rogers static bool config_term_shrinked; 77458d3a4ceSIan Rogers 77558d3a4ceSIan Rogers static const char *config_term_name(enum parse_events__term_type term_type) 77658d3a4ceSIan Rogers { 77717cb5f84SWang Nan /* 77817cb5f84SWang Nan * Update according to parse-events.l 77917cb5f84SWang Nan */ 78017cb5f84SWang Nan static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = { 78117cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_USER] = "<sysfs term>", 78217cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_CONFIG] = "config", 78317cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_CONFIG1] = "config1", 78417cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_CONFIG2] = "config2", 785204e7c49SRob Herring [PARSE_EVENTS__TERM_TYPE_CONFIG3] = "config3", 78617cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_NAME] = "name", 78717cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD] = "period", 78817cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ] = "freq", 78917cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE] = "branch_type", 79017cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_TIME] = "time", 79117cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_CALLGRAPH] = "call-graph", 79217cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_STACKSIZE] = "stack-size", 79317cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_NOINHERIT] = "no-inherit", 79417cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_INHERIT] = "inherit", 795792d48b4SArnaldo Carvalho de Melo [PARSE_EVENTS__TERM_TYPE_MAX_STACK] = "max-stack", 7962fda5adaSArnaldo Carvalho de Melo [PARSE_EVENTS__TERM_TYPE_MAX_EVENTS] = "nr", 797626a6b78SWang Nan [PARSE_EVENTS__TERM_TYPE_OVERWRITE] = "overwrite", 798626a6b78SWang Nan [PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite", 799dd60fba7SMathieu Poirier [PARSE_EVENTS__TERM_TYPE_DRV_CFG] = "driver-config", 800064b4e82SJin Yao [PARSE_EVENTS__TERM_TYPE_PERCORE] = "percore", 8011b992154SAdrian Hunter [PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT] = "aux-output", 802eb7a52d4SAdrian Hunter [PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE] = "aux-sample-size", 8032b62b3a6SIan Rogers [PARSE_EVENTS__TERM_TYPE_METRIC_ID] = "metric-id", 80470c90e4aSIan Rogers [PARSE_EVENTS__TERM_TYPE_RAW] = "raw", 8056fd1e519SIan Rogers [PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE] = "legacy-cache", 8065ea8f2ccSIan Rogers [PARSE_EVENTS__TERM_TYPE_HARDWARE] = "hardware", 80717cb5f84SWang Nan }; 80858d3a4ceSIan Rogers if ((unsigned int)term_type >= __PARSE_EVENTS__TERM_TYPE_NR) 80958d3a4ceSIan Rogers return "unknown term"; 81017cb5f84SWang Nan 81158d3a4ceSIan Rogers return config_term_names[term_type]; 81258d3a4ceSIan Rogers } 8131669e509SWang Nan 8141669e509SWang Nan static bool 81558d3a4ceSIan Rogers config_term_avail(enum parse_events__term_type term_type, struct parse_events_error *err) 8161669e509SWang Nan { 817448d732cSIan Rogers char *err_str; 818448d732cSIan Rogers 8191669e509SWang Nan if (term_type < 0 || term_type >= __PARSE_EVENTS__TERM_TYPE_NR) { 8206c191289SIan Rogers parse_events_error__handle(err, -1, 821448d732cSIan Rogers strdup("Invalid term_type"), NULL); 8221669e509SWang Nan return false; 8231669e509SWang Nan } 8241669e509SWang Nan if (!config_term_shrinked) 8251669e509SWang Nan return true; 8261669e509SWang Nan 8271669e509SWang Nan switch (term_type) { 8281669e509SWang Nan case PARSE_EVENTS__TERM_TYPE_CONFIG: 8291669e509SWang Nan case PARSE_EVENTS__TERM_TYPE_CONFIG1: 8301669e509SWang Nan case PARSE_EVENTS__TERM_TYPE_CONFIG2: 831204e7c49SRob Herring case PARSE_EVENTS__TERM_TYPE_CONFIG3: 8321669e509SWang Nan case PARSE_EVENTS__TERM_TYPE_NAME: 8332b62b3a6SIan Rogers case PARSE_EVENTS__TERM_TYPE_METRIC_ID: 83406835545SSukadev Bhattiprolu case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: 835064b4e82SJin Yao case PARSE_EVENTS__TERM_TYPE_PERCORE: 8361669e509SWang Nan return true; 83758d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_USER: 83858d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ: 83958d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE: 84058d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_TIME: 84158d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: 84258d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 84358d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 84458d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_INHERIT: 84558d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_MAX_STACK: 84658d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS: 84758d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: 84858d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_OVERWRITE: 84958d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_DRV_CFG: 85058d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT: 85158d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE: 85258d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_RAW: 85358d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE: 85458d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_HARDWARE: 8551669e509SWang Nan default: 8561669e509SWang Nan if (!err) 8571669e509SWang Nan return false; 8581669e509SWang Nan 8591669e509SWang Nan /* term_type is validated so indexing is safe */ 860448d732cSIan Rogers if (asprintf(&err_str, "'%s' is not usable in 'perf stat'", 86158d3a4ceSIan Rogers config_term_name(term_type)) >= 0) 8626c191289SIan Rogers parse_events_error__handle(err, -1, err_str, NULL); 8631669e509SWang Nan return false; 8641669e509SWang Nan } 8651669e509SWang Nan } 8661669e509SWang Nan 8671669e509SWang Nan void parse_events__shrink_config_terms(void) 8681669e509SWang Nan { 8691669e509SWang Nan config_term_shrinked = true; 8701669e509SWang Nan } 8711669e509SWang Nan 8720b8891a8SHe Kuang static int config_term_common(struct perf_event_attr *attr, 8733b0e371cSJiri Olsa struct parse_events_term *term, 8743b0e371cSJiri Olsa struct parse_events_error *err) 8758f707d84SJiri Olsa { 87616fa7e82SJiri Olsa #define CHECK_TYPE_VAL(type) \ 87716fa7e82SJiri Olsa do { \ 8783b0e371cSJiri Olsa if (check_type_val(term, err, PARSE_EVENTS__TERM_TYPE_ ## type)) \ 87916fa7e82SJiri Olsa return -EINVAL; \ 88016fa7e82SJiri Olsa } while (0) 88116fa7e82SJiri Olsa 88216fa7e82SJiri Olsa switch (term->type_term) { 8838f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_CONFIG: 88416fa7e82SJiri Olsa CHECK_TYPE_VAL(NUM); 8858f707d84SJiri Olsa attr->config = term->val.num; 8868f707d84SJiri Olsa break; 8878f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_CONFIG1: 88816fa7e82SJiri Olsa CHECK_TYPE_VAL(NUM); 8898f707d84SJiri Olsa attr->config1 = term->val.num; 8908f707d84SJiri Olsa break; 8918f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_CONFIG2: 89216fa7e82SJiri Olsa CHECK_TYPE_VAL(NUM); 8938f707d84SJiri Olsa attr->config2 = term->val.num; 8948f707d84SJiri Olsa break; 895204e7c49SRob Herring case PARSE_EVENTS__TERM_TYPE_CONFIG3: 896204e7c49SRob Herring CHECK_TYPE_VAL(NUM); 897204e7c49SRob Herring attr->config3 = term->val.num; 898204e7c49SRob Herring break; 8998f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: 90016fa7e82SJiri Olsa CHECK_TYPE_VAL(NUM); 9018f707d84SJiri Olsa break; 90209af2a55SNamhyung Kim case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ: 90309af2a55SNamhyung Kim CHECK_TYPE_VAL(NUM); 90409af2a55SNamhyung Kim break; 9058f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE: 906ac12f676SAndi Kleen CHECK_TYPE_VAL(STR); 907ac12f676SAndi Kleen if (strcmp(term->val.str, "no") && 908448d732cSIan Rogers parse_branch_str(term->val.str, 909448d732cSIan Rogers &attr->branch_sample_type)) { 9106c191289SIan Rogers parse_events_error__handle(err, term->err_val, 911448d732cSIan Rogers strdup("invalid branch sample type"), 912448d732cSIan Rogers NULL); 913ac12f676SAndi Kleen return -EINVAL; 914ac12f676SAndi Kleen } 9158f707d84SJiri Olsa break; 91632067712SKan Liang case PARSE_EVENTS__TERM_TYPE_TIME: 91732067712SKan Liang CHECK_TYPE_VAL(NUM); 91832067712SKan Liang if (term->val.num > 1) { 9196c191289SIan Rogers parse_events_error__handle(err, term->err_val, 920448d732cSIan Rogers strdup("expected 0 or 1"), 921448d732cSIan Rogers NULL); 92232067712SKan Liang return -EINVAL; 92332067712SKan Liang } 92432067712SKan Liang break; 925d457c963SKan Liang case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: 926d457c963SKan Liang CHECK_TYPE_VAL(STR); 927d457c963SKan Liang break; 928d457c963SKan Liang case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 929d457c963SKan Liang CHECK_TYPE_VAL(NUM); 930d457c963SKan Liang break; 931374ce938SWang Nan case PARSE_EVENTS__TERM_TYPE_INHERIT: 932374ce938SWang Nan CHECK_TYPE_VAL(NUM); 933374ce938SWang Nan break; 934374ce938SWang Nan case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 935374ce938SWang Nan CHECK_TYPE_VAL(NUM); 936374ce938SWang Nan break; 937626a6b78SWang Nan case PARSE_EVENTS__TERM_TYPE_OVERWRITE: 938626a6b78SWang Nan CHECK_TYPE_VAL(NUM); 939626a6b78SWang Nan break; 940626a6b78SWang Nan case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: 941626a6b78SWang Nan CHECK_TYPE_VAL(NUM); 942626a6b78SWang Nan break; 9436b5fc39bSJiri Olsa case PARSE_EVENTS__TERM_TYPE_NAME: 9446b5fc39bSJiri Olsa CHECK_TYPE_VAL(STR); 9456b5fc39bSJiri Olsa break; 9462b62b3a6SIan Rogers case PARSE_EVENTS__TERM_TYPE_METRIC_ID: 9472b62b3a6SIan Rogers CHECK_TYPE_VAL(STR); 9482b62b3a6SIan Rogers break; 94970c90e4aSIan Rogers case PARSE_EVENTS__TERM_TYPE_RAW: 95070c90e4aSIan Rogers CHECK_TYPE_VAL(STR); 95170c90e4aSIan Rogers break; 952792d48b4SArnaldo Carvalho de Melo case PARSE_EVENTS__TERM_TYPE_MAX_STACK: 953792d48b4SArnaldo Carvalho de Melo CHECK_TYPE_VAL(NUM); 954792d48b4SArnaldo Carvalho de Melo break; 9552fda5adaSArnaldo Carvalho de Melo case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS: 9562fda5adaSArnaldo Carvalho de Melo CHECK_TYPE_VAL(NUM); 9572fda5adaSArnaldo Carvalho de Melo break; 958064b4e82SJin Yao case PARSE_EVENTS__TERM_TYPE_PERCORE: 959064b4e82SJin Yao CHECK_TYPE_VAL(NUM); 960064b4e82SJin Yao if ((unsigned int)term->val.num > 1) { 9616c191289SIan Rogers parse_events_error__handle(err, term->err_val, 962448d732cSIan Rogers strdup("expected 0 or 1"), 963448d732cSIan Rogers NULL); 964064b4e82SJin Yao return -EINVAL; 965064b4e82SJin Yao } 966064b4e82SJin Yao break; 9671b992154SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT: 9681b992154SAdrian Hunter CHECK_TYPE_VAL(NUM); 9691b992154SAdrian Hunter break; 970eb7a52d4SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE: 971eb7a52d4SAdrian Hunter CHECK_TYPE_VAL(NUM); 972eb7a52d4SAdrian Hunter if (term->val.num > UINT_MAX) { 9736c191289SIan Rogers parse_events_error__handle(err, term->err_val, 974eb7a52d4SAdrian Hunter strdup("too big"), 975eb7a52d4SAdrian Hunter NULL); 976eb7a52d4SAdrian Hunter return -EINVAL; 977eb7a52d4SAdrian Hunter } 978eb7a52d4SAdrian Hunter break; 97958d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_DRV_CFG: 98058d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_USER: 98158d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE: 98258d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_HARDWARE: 9838f707d84SJiri Olsa default: 9846c191289SIan Rogers parse_events_error__handle(err, term->err_term, 98558d3a4ceSIan Rogers strdup(config_term_name(term->type_term)), 986448d732cSIan Rogers parse_events_formats_error_string(NULL)); 9878f707d84SJiri Olsa return -EINVAL; 9888f707d84SJiri Olsa } 98916fa7e82SJiri Olsa 9901669e509SWang Nan /* 9914d39c89fSIngo Molnar * Check term availability after basic checking so 9921669e509SWang Nan * PARSE_EVENTS__TERM_TYPE_USER can be found and filtered. 9931669e509SWang Nan * 9944d39c89fSIngo Molnar * If check availability at the entry of this function, 9951669e509SWang Nan * user will see "'<sysfs term>' is not usable in 'perf stat'" 9961669e509SWang Nan * if an invalid config term is provided for legacy events 9971669e509SWang Nan * (for example, instructions/badterm/...), which is confusing. 9981669e509SWang Nan */ 9991669e509SWang Nan if (!config_term_avail(term->type_term, err)) 10001669e509SWang Nan return -EINVAL; 10018f707d84SJiri Olsa return 0; 100216fa7e82SJiri Olsa #undef CHECK_TYPE_VAL 10038f707d84SJiri Olsa } 10048f707d84SJiri Olsa 10050b8891a8SHe Kuang static int config_term_pmu(struct perf_event_attr *attr, 10060b8891a8SHe Kuang struct parse_events_term *term, 10070b8891a8SHe Kuang struct parse_events_error *err) 10080b8891a8SHe Kuang { 10096fd1e519SIan Rogers if (term->type_term == PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE) { 1010a24d9d9dSIan Rogers struct perf_pmu *pmu = perf_pmus__find_by_type(attr->type); 10116fd1e519SIan Rogers 10125b10c18dSIan Rogers if (!pmu) { 10135b10c18dSIan Rogers char *err_str; 10145b10c18dSIan Rogers 10155b10c18dSIan Rogers if (asprintf(&err_str, "Failed to find PMU for type %d", attr->type) >= 0) 10165b10c18dSIan Rogers parse_events_error__handle(err, term->err_term, 10175b10c18dSIan Rogers err_str, /*help=*/NULL); 10185b10c18dSIan Rogers return -EINVAL; 10195b10c18dSIan Rogers } 1020a24d9d9dSIan Rogers /* 1021a24d9d9dSIan Rogers * Rewrite the PMU event to a legacy cache one unless the PMU 1022a24d9d9dSIan Rogers * doesn't support legacy cache events or the event is present 1023a24d9d9dSIan Rogers * within the PMU. 1024a24d9d9dSIan Rogers */ 1025a24d9d9dSIan Rogers if (perf_pmu__supports_legacy_cache(pmu) && 1026a24d9d9dSIan Rogers !perf_pmu__have_event(pmu, term->config)) { 10276fd1e519SIan Rogers attr->type = PERF_TYPE_HW_CACHE; 10286fd1e519SIan Rogers return parse_events__decode_legacy_cache(term->config, pmu->type, 10296fd1e519SIan Rogers &attr->config); 1030a24d9d9dSIan Rogers } else { 10316fd1e519SIan Rogers term->type_term = PARSE_EVENTS__TERM_TYPE_USER; 1032a24d9d9dSIan Rogers term->no_value = true; 1033a24d9d9dSIan Rogers } 10346fd1e519SIan Rogers } 10355ea8f2ccSIan Rogers if (term->type_term == PARSE_EVENTS__TERM_TYPE_HARDWARE) { 1036a24d9d9dSIan Rogers struct perf_pmu *pmu = perf_pmus__find_by_type(attr->type); 10375ea8f2ccSIan Rogers 10385ea8f2ccSIan Rogers if (!pmu) { 1039251aa040SIan Rogers char *err_str; 1040251aa040SIan Rogers 1041251aa040SIan Rogers if (asprintf(&err_str, "Failed to find PMU for type %d", attr->type) >= 0) 1042251aa040SIan Rogers parse_events_error__handle(err, term->err_term, 1043251aa040SIan Rogers err_str, /*help=*/NULL); 10445ea8f2ccSIan Rogers return -EINVAL; 10455ea8f2ccSIan Rogers } 1046a24d9d9dSIan Rogers /* 1047a24d9d9dSIan Rogers * If the PMU has a sysfs or json event prefer it over 1048a24d9d9dSIan Rogers * legacy. ARM requires this. 1049a24d9d9dSIan Rogers */ 1050a24d9d9dSIan Rogers if (perf_pmu__have_event(pmu, term->config)) { 1051a24d9d9dSIan Rogers term->type_term = PARSE_EVENTS__TERM_TYPE_USER; 1052a24d9d9dSIan Rogers term->no_value = true; 1053a24d9d9dSIan Rogers } else { 10545ea8f2ccSIan Rogers attr->type = PERF_TYPE_HARDWARE; 1055251aa040SIan Rogers attr->config = term->val.num; 1056251aa040SIan Rogers if (perf_pmus__supports_extended_type()) 1057251aa040SIan Rogers attr->config |= (__u64)pmu->type << PERF_PMU_TYPE_SHIFT; 1058a24d9d9dSIan Rogers } 10595ea8f2ccSIan Rogers return 0; 10605ea8f2ccSIan Rogers } 1061dd60fba7SMathieu Poirier if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER || 10626fd1e519SIan Rogers term->type_term == PARSE_EVENTS__TERM_TYPE_DRV_CFG) { 10630b8891a8SHe Kuang /* 10640b8891a8SHe Kuang * Always succeed for sysfs terms, as we dont know 10650b8891a8SHe Kuang * at this point what type they need to have. 10660b8891a8SHe Kuang */ 10670b8891a8SHe Kuang return 0; 10686fd1e519SIan Rogers } 10690b8891a8SHe Kuang return config_term_common(attr, term, err); 10700b8891a8SHe Kuang } 10710b8891a8SHe Kuang 1072378ef0f5SIan Rogers #ifdef HAVE_LIBTRACEEVENT 1073e637d177SHe Kuang static int config_term_tracepoint(struct perf_event_attr *attr, 1074e637d177SHe Kuang struct parse_events_term *term, 1075e637d177SHe Kuang struct parse_events_error *err) 1076e637d177SHe Kuang { 1077e637d177SHe Kuang switch (term->type_term) { 1078e637d177SHe Kuang case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: 1079e637d177SHe Kuang case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 1080374ce938SWang Nan case PARSE_EVENTS__TERM_TYPE_INHERIT: 1081374ce938SWang Nan case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 1082792d48b4SArnaldo Carvalho de Melo case PARSE_EVENTS__TERM_TYPE_MAX_STACK: 10832fda5adaSArnaldo Carvalho de Melo case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS: 1084626a6b78SWang Nan case PARSE_EVENTS__TERM_TYPE_OVERWRITE: 1085626a6b78SWang Nan case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: 10861b992154SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT: 1087eb7a52d4SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE: 1088e637d177SHe Kuang return config_term_common(attr, term, err); 108958d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_USER: 109058d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_CONFIG: 109158d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_CONFIG1: 109258d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_CONFIG2: 109358d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_CONFIG3: 109458d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_NAME: 109558d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: 109658d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ: 109758d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE: 109858d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_TIME: 109958d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_DRV_CFG: 110058d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_PERCORE: 110158d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_METRIC_ID: 110258d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_RAW: 110358d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE: 110458d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_HARDWARE: 1105e637d177SHe Kuang default: 1106e637d177SHe Kuang if (err) { 11076c191289SIan Rogers parse_events_error__handle(err, term->err_term, 110858d3a4ceSIan Rogers strdup(config_term_name(term->type_term)), 1109448d732cSIan Rogers strdup("valid terms: call-graph,stack-size\n")); 1110e637d177SHe Kuang } 1111e637d177SHe Kuang return -EINVAL; 1112e637d177SHe Kuang } 1113e637d177SHe Kuang 1114e637d177SHe Kuang return 0; 1115e637d177SHe Kuang } 1116378ef0f5SIan Rogers #endif 1117e637d177SHe Kuang 11188f707d84SJiri Olsa static int config_attr(struct perf_event_attr *attr, 11195ccc4edfSIan Rogers const struct parse_events_terms *head, 11200b8891a8SHe Kuang struct parse_events_error *err, 11210b8891a8SHe Kuang config_term_func_t config_term) 11228f707d84SJiri Olsa { 11236cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term; 11248f707d84SJiri Olsa 11250d3f0e6fSIan Rogers list_for_each_entry(term, &head->terms, list) 11263b0e371cSJiri Olsa if (config_term(attr, term, err)) 11278f707d84SJiri Olsa return -EINVAL; 11288f707d84SJiri Olsa 11298f707d84SJiri Olsa return 0; 11308f707d84SJiri Olsa } 11318f707d84SJiri Olsa 11325ccc4edfSIan Rogers static int get_config_terms(const struct parse_events_terms *head_config, 11335ccc4edfSIan Rogers struct list_head *head_terms) 1134930a2e29SJiri Olsa { 113505e54e23SIan Rogers #define ADD_CONFIG_TERM(__type, __weak) \ 113635ac0cadSArnaldo Carvalho de Melo struct evsel_config_term *__t; \ 1137930a2e29SJiri Olsa \ 1138930a2e29SJiri Olsa __t = zalloc(sizeof(*__t)); \ 1139930a2e29SJiri Olsa if (!__t) \ 1140930a2e29SJiri Olsa return -ENOMEM; \ 1141930a2e29SJiri Olsa \ 1142930a2e29SJiri Olsa INIT_LIST_HEAD(&__t->list); \ 114335ac0cadSArnaldo Carvalho de Melo __t->type = EVSEL__CONFIG_TERM_ ## __type; \ 114405e54e23SIan Rogers __t->weak = __weak; \ 1145e884602bSLeo Yan list_add_tail(&__t->list, head_terms) 1146e884602bSLeo Yan 114705e54e23SIan Rogers #define ADD_CONFIG_TERM_VAL(__type, __name, __val, __weak) \ 1148e884602bSLeo Yan do { \ 114905e54e23SIan Rogers ADD_CONFIG_TERM(__type, __weak); \ 1150e884602bSLeo Yan __t->val.__name = __val; \ 1151e884602bSLeo Yan } while (0) 1152e884602bSLeo Yan 115305e54e23SIan Rogers #define ADD_CONFIG_TERM_STR(__type, __val, __weak) \ 1154e884602bSLeo Yan do { \ 115505e54e23SIan Rogers ADD_CONFIG_TERM(__type, __weak); \ 11563220fb8dSLeo Yan __t->val.str = strdup(__val); \ 11573220fb8dSLeo Yan if (!__t->val.str) { \ 11583220fb8dSLeo Yan zfree(&__t); \ 11593220fb8dSLeo Yan return -ENOMEM; \ 11603220fb8dSLeo Yan } \ 11613220fb8dSLeo Yan __t->free_str = true; \ 1162930a2e29SJiri Olsa } while (0) 1163930a2e29SJiri Olsa 1164930a2e29SJiri Olsa struct parse_events_term *term; 1165930a2e29SJiri Olsa 11660d3f0e6fSIan Rogers list_for_each_entry(term, &head_config->terms, list) { 1167930a2e29SJiri Olsa switch (term->type_term) { 1168ee4c7588SJiri Olsa case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: 116905e54e23SIan Rogers ADD_CONFIG_TERM_VAL(PERIOD, period, term->val.num, term->weak); 117032067712SKan Liang break; 117109af2a55SNamhyung Kim case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ: 117205e54e23SIan Rogers ADD_CONFIG_TERM_VAL(FREQ, freq, term->val.num, term->weak); 117309af2a55SNamhyung Kim break; 117432067712SKan Liang case PARSE_EVENTS__TERM_TYPE_TIME: 117505e54e23SIan Rogers ADD_CONFIG_TERM_VAL(TIME, time, term->val.num, term->weak); 117632067712SKan Liang break; 1177d457c963SKan Liang case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: 117805e54e23SIan Rogers ADD_CONFIG_TERM_STR(CALLGRAPH, term->val.str, term->weak); 1179d457c963SKan Liang break; 1180ac12f676SAndi Kleen case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE: 118105e54e23SIan Rogers ADD_CONFIG_TERM_STR(BRANCH, term->val.str, term->weak); 1182ac12f676SAndi Kleen break; 1183d457c963SKan Liang case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 1184e884602bSLeo Yan ADD_CONFIG_TERM_VAL(STACK_USER, stack_user, 118505e54e23SIan Rogers term->val.num, term->weak); 1186d457c963SKan Liang break; 1187374ce938SWang Nan case PARSE_EVENTS__TERM_TYPE_INHERIT: 1188e884602bSLeo Yan ADD_CONFIG_TERM_VAL(INHERIT, inherit, 118905e54e23SIan Rogers term->val.num ? 1 : 0, term->weak); 1190374ce938SWang Nan break; 1191374ce938SWang Nan case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 1192e884602bSLeo Yan ADD_CONFIG_TERM_VAL(INHERIT, inherit, 119305e54e23SIan Rogers term->val.num ? 0 : 1, term->weak); 1194374ce938SWang Nan break; 1195792d48b4SArnaldo Carvalho de Melo case PARSE_EVENTS__TERM_TYPE_MAX_STACK: 1196e884602bSLeo Yan ADD_CONFIG_TERM_VAL(MAX_STACK, max_stack, 119705e54e23SIan Rogers term->val.num, term->weak); 1198792d48b4SArnaldo Carvalho de Melo break; 11992fda5adaSArnaldo Carvalho de Melo case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS: 1200e884602bSLeo Yan ADD_CONFIG_TERM_VAL(MAX_EVENTS, max_events, 120105e54e23SIan Rogers term->val.num, term->weak); 12022fda5adaSArnaldo Carvalho de Melo break; 1203626a6b78SWang Nan case PARSE_EVENTS__TERM_TYPE_OVERWRITE: 1204e884602bSLeo Yan ADD_CONFIG_TERM_VAL(OVERWRITE, overwrite, 120505e54e23SIan Rogers term->val.num ? 1 : 0, term->weak); 1206626a6b78SWang Nan break; 1207626a6b78SWang Nan case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: 1208e884602bSLeo Yan ADD_CONFIG_TERM_VAL(OVERWRITE, overwrite, 120905e54e23SIan Rogers term->val.num ? 0 : 1, term->weak); 1210626a6b78SWang Nan break; 1211dd60fba7SMathieu Poirier case PARSE_EVENTS__TERM_TYPE_DRV_CFG: 121205e54e23SIan Rogers ADD_CONFIG_TERM_STR(DRV_CFG, term->val.str, term->weak); 1213dd60fba7SMathieu Poirier break; 1214064b4e82SJin Yao case PARSE_EVENTS__TERM_TYPE_PERCORE: 1215e884602bSLeo Yan ADD_CONFIG_TERM_VAL(PERCORE, percore, 121605e54e23SIan Rogers term->val.num ? true : false, term->weak); 1217064b4e82SJin Yao break; 12181b992154SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT: 1219e884602bSLeo Yan ADD_CONFIG_TERM_VAL(AUX_OUTPUT, aux_output, 122005e54e23SIan Rogers term->val.num ? 1 : 0, term->weak); 12211b992154SAdrian Hunter break; 1222eb7a52d4SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE: 1223e884602bSLeo Yan ADD_CONFIG_TERM_VAL(AUX_SAMPLE_SIZE, aux_sample_size, 122405e54e23SIan Rogers term->val.num, term->weak); 1225eb7a52d4SAdrian Hunter break; 122658d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_USER: 122758d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_CONFIG: 122858d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_CONFIG1: 122958d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_CONFIG2: 123058d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_CONFIG3: 123158d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_NAME: 123258d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_METRIC_ID: 123358d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_RAW: 123458d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE: 123558d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_HARDWARE: 1236930a2e29SJiri Olsa default: 1237930a2e29SJiri Olsa break; 1238930a2e29SJiri Olsa } 1239930a2e29SJiri Olsa } 1240a1ac7de6SAdrian Hunter return 0; 1241a1ac7de6SAdrian Hunter } 1242a1ac7de6SAdrian Hunter 1243a1ac7de6SAdrian Hunter /* 124435ac0cadSArnaldo Carvalho de Melo * Add EVSEL__CONFIG_TERM_CFG_CHG where cfg_chg will have a bit set for 1245a1ac7de6SAdrian Hunter * each bit of attr->config that the user has changed. 1246a1ac7de6SAdrian Hunter */ 12470d3f0e6fSIan Rogers static int get_config_chgs(struct perf_pmu *pmu, struct parse_events_terms *head_config, 1248a1ac7de6SAdrian Hunter struct list_head *head_terms) 1249a1ac7de6SAdrian Hunter { 1250a1ac7de6SAdrian Hunter struct parse_events_term *term; 1251a1ac7de6SAdrian Hunter u64 bits = 0; 1252a1ac7de6SAdrian Hunter int type; 1253a1ac7de6SAdrian Hunter 12540d3f0e6fSIan Rogers list_for_each_entry(term, &head_config->terms, list) { 1255a1ac7de6SAdrian Hunter switch (term->type_term) { 1256a1ac7de6SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_USER: 12577eb54733SIan Rogers type = perf_pmu__format_type(pmu, term->config); 1258a1ac7de6SAdrian Hunter if (type != PERF_PMU_FORMAT_VALUE_CONFIG) 1259a1ac7de6SAdrian Hunter continue; 1260da6a5afdSIan Rogers bits |= perf_pmu__format_bits(pmu, term->config); 1261a1ac7de6SAdrian Hunter break; 1262a1ac7de6SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_CONFIG: 1263a1ac7de6SAdrian Hunter bits = ~(u64)0; 1264a1ac7de6SAdrian Hunter break; 126558d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_CONFIG1: 126658d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_CONFIG2: 126758d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_CONFIG3: 126858d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_NAME: 126958d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: 127058d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ: 127158d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE: 127258d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_TIME: 127358d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: 127458d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 127558d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 127658d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_INHERIT: 127758d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_MAX_STACK: 127858d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS: 127958d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: 128058d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_OVERWRITE: 128158d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_DRV_CFG: 128258d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_PERCORE: 128358d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT: 128458d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE: 128558d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_METRIC_ID: 128658d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_RAW: 128758d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE: 128858d3a4ceSIan Rogers case PARSE_EVENTS__TERM_TYPE_HARDWARE: 1289a1ac7de6SAdrian Hunter default: 1290a1ac7de6SAdrian Hunter break; 1291a1ac7de6SAdrian Hunter } 1292a1ac7de6SAdrian Hunter } 1293a1ac7de6SAdrian Hunter 1294a1ac7de6SAdrian Hunter if (bits) 129505e54e23SIan Rogers ADD_CONFIG_TERM_VAL(CFG_CHG, cfg_chg, bits, false); 1296a1ac7de6SAdrian Hunter 1297a1ac7de6SAdrian Hunter #undef ADD_CONFIG_TERM 1298930a2e29SJiri Olsa return 0; 1299930a2e29SJiri Olsa } 1300930a2e29SJiri Olsa 130111a42964SDominique Martinet int parse_events_add_tracepoint(struct parse_events_state *parse_state, 130211a42964SDominique Martinet struct list_head *list, 13038c619d6aSWang Nan const char *sys, const char *event, 1304272ed29aSJiri Olsa struct parse_events_error *err, 13050d3f0e6fSIan Rogers struct parse_events_terms *head_config, void *loc_) 1306e637d177SHe Kuang { 1307d81fa63bSIan Rogers YYLTYPE *loc = loc_; 1308378ef0f5SIan Rogers #ifdef HAVE_LIBTRACEEVENT 1309e637d177SHe Kuang if (head_config) { 1310e637d177SHe Kuang struct perf_event_attr attr; 1311e637d177SHe Kuang 1312272ed29aSJiri Olsa if (config_attr(&attr, head_config, err, 1313e637d177SHe Kuang config_term_tracepoint)) 1314e637d177SHe Kuang return -EINVAL; 1315e637d177SHe Kuang } 1316e637d177SHe Kuang 1317e637d177SHe Kuang if (strpbrk(sys, "*?")) 131811a42964SDominique Martinet return add_tracepoint_multi_sys(parse_state, list, sys, event, 1319d81fa63bSIan Rogers err, head_config, loc); 1320e637d177SHe Kuang else 132111a42964SDominique Martinet return add_tracepoint_event(parse_state, list, sys, event, 1322d81fa63bSIan Rogers err, head_config, loc); 1323378ef0f5SIan Rogers #else 132411a42964SDominique Martinet (void)parse_state; 1325378ef0f5SIan Rogers (void)list; 1326378ef0f5SIan Rogers (void)sys; 1327378ef0f5SIan Rogers (void)event; 1328378ef0f5SIan Rogers (void)head_config; 1329d81fa63bSIan Rogers parse_events_error__handle(err, loc->first_column, strdup("unsupported tracepoint"), 1330378ef0f5SIan Rogers strdup("libtraceevent is necessary for tracepoint support")); 1331378ef0f5SIan Rogers return -1; 1332378ef0f5SIan Rogers #endif 1333e637d177SHe Kuang } 1334e637d177SHe Kuang 13358bc75f69SIan Rogers static int __parse_events_add_numeric(struct parse_events_state *parse_state, 133687d650beSJiri Olsa struct list_head *list, 1337251aa040SIan Rogers struct perf_pmu *pmu, u32 type, u32 extended_type, 13385ccc4edfSIan Rogers u64 config, const struct parse_events_terms *head_config) 133974d5b588SJaswinder Singh Rajput { 134089812fc8SJiri Olsa struct perf_event_attr attr; 1341930a2e29SJiri Olsa LIST_HEAD(config_terms); 13422b62b3a6SIan Rogers const char *name, *metric_id; 13439cbfa2f6SJin Yao int ret; 134474d5b588SJaswinder Singh Rajput 134589812fc8SJiri Olsa memset(&attr, 0, sizeof(attr)); 134689812fc8SJiri Olsa attr.type = type; 134789812fc8SJiri Olsa attr.config = config; 1348251aa040SIan Rogers if (extended_type && (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE)) { 1349251aa040SIan Rogers assert(perf_pmus__supports_extended_type()); 1350251aa040SIan Rogers attr.config |= (u64)extended_type << PERF_PMU_TYPE_SHIFT; 1351240de691Sbaomingtong001@208suo.com } 13528f707d84SJiri Olsa 1353930a2e29SJiri Olsa if (head_config) { 13545d9cdc11SArnaldo Carvalho de Melo if (config_attr(&attr, head_config, parse_state->error, 13550b8891a8SHe Kuang config_term_common)) 13568f707d84SJiri Olsa return -EINVAL; 13578f707d84SJiri Olsa 1358930a2e29SJiri Olsa if (get_config_terms(head_config, &config_terms)) 1359930a2e29SJiri Olsa return -ENOMEM; 1360930a2e29SJiri Olsa } 1361930a2e29SJiri Olsa 13622b62b3a6SIan Rogers name = get_config_name(head_config); 13632b62b3a6SIan Rogers metric_id = get_config_metric_id(head_config); 13648bc75f69SIan Rogers ret = __add_event(list, &parse_state->idx, &attr, /*init_attr*/true, name, 13658bc75f69SIan Rogers metric_id, pmu, &config_terms, /*auto_merge_stats=*/false, 13668bc75f69SIan Rogers /*cpu_list=*/NULL) ? 0 : -ENOMEM; 136799fc5941SAdrian Hunter free_config_terms(&config_terms); 136899fc5941SAdrian Hunter return ret; 1369b908debdSIngo Molnar } 1370b908debdSIngo Molnar 13718bc75f69SIan Rogers int parse_events_add_numeric(struct parse_events_state *parse_state, 13728bc75f69SIan Rogers struct list_head *list, 13738bc75f69SIan Rogers u32 type, u64 config, 13745ccc4edfSIan Rogers const struct parse_events_terms *head_config, 13758bc75f69SIan Rogers bool wildcard) 13768bc75f69SIan Rogers { 13778bc75f69SIan Rogers struct perf_pmu *pmu = NULL; 13788bc75f69SIan Rogers bool found_supported = false; 13798bc75f69SIan Rogers 13809d6a1df9SIan Rogers /* Wildcards on numeric values are only supported by core PMUs. */ 1381251aa040SIan Rogers if (wildcard && perf_pmus__supports_extended_type()) { 13829d6a1df9SIan Rogers while ((pmu = perf_pmus__scan_core(pmu)) != NULL) { 13838bc75f69SIan Rogers int ret; 13848bc75f69SIan Rogers 1385251aa040SIan Rogers found_supported = true; 1386411ad22eSIan Rogers if (parse_events__filter_pmu(parse_state, pmu)) 1387411ad22eSIan Rogers continue; 1388411ad22eSIan Rogers 1389251aa040SIan Rogers ret = __parse_events_add_numeric(parse_state, list, pmu, 1390251aa040SIan Rogers type, pmu->type, 13918bc75f69SIan Rogers config, head_config); 13928bc75f69SIan Rogers if (ret) 13938bc75f69SIan Rogers return ret; 13948bc75f69SIan Rogers } 1395251aa040SIan Rogers if (found_supported) 1396251aa040SIan Rogers return 0; 1397251aa040SIan Rogers } 1398251aa040SIan Rogers return __parse_events_add_numeric(parse_state, list, perf_pmus__find_by_type(type), 1399251aa040SIan Rogers type, /*extended_type=*/0, config, head_config); 14008bc75f69SIan Rogers } 14018bc75f69SIan Rogers 1402f0fbb114SAndi Kleen int parse_events_add_tool(struct parse_events_state *parse_state, 1403f0fbb114SAndi Kleen struct list_head *list, 14048228e936SIan Rogers int tool_event) 1405f0fbb114SAndi Kleen { 1406f0fbb114SAndi Kleen return add_event_tool(list, &parse_state->idx, tool_event); 1407f0fbb114SAndi Kleen } 1408f0fbb114SAndi Kleen 1409064b4e82SJin Yao static bool config_term_percore(struct list_head *config_terms) 1410064b4e82SJin Yao { 141135ac0cadSArnaldo Carvalho de Melo struct evsel_config_term *term; 1412064b4e82SJin Yao 1413064b4e82SJin Yao list_for_each_entry(term, config_terms, list) { 141435ac0cadSArnaldo Carvalho de Melo if (term->type == EVSEL__CONFIG_TERM_PERCORE) 1415064b4e82SJin Yao return term->val.percore; 1416064b4e82SJin Yao } 1417064b4e82SJin Yao 1418064b4e82SJin Yao return false; 1419064b4e82SJin Yao } 1420064b4e82SJin Yao 14218b734eaaSIan Rogers static int parse_events_add_pmu(struct parse_events_state *parse_state, 142263dfcde9SIan Rogers struct list_head *list, struct perf_pmu *pmu, 14230d3f0e6fSIan Rogers const struct parse_events_terms *const_parsed_terms, 142463dfcde9SIan Rogers bool auto_merge_stats) 14255f537a26SJiri Olsa { 14265f537a26SJiri Olsa struct perf_event_attr attr; 142746441bdcSMatt Fleming struct perf_pmu_info info; 142832dcd021SJiri Olsa struct evsel *evsel; 1429333b5665SAndi Kleen struct parse_events_error *err = parse_state->error; 1430930a2e29SJiri Olsa LIST_HEAD(config_terms); 14310d3f0e6fSIan Rogers struct parse_events_terms parsed_terms; 1432a24d9d9dSIan Rogers bool alias_rewrote_terms = false; 14335f537a26SJiri Olsa 14347a6e9164SIan Rogers if (verbose > 1) { 14357a6e9164SIan Rogers struct strbuf sb; 14367a6e9164SIan Rogers 14377a6e9164SIan Rogers strbuf_init(&sb, /*hint=*/ 0); 143890b2c210SIan Rogers if (pmu->selectable && const_parsed_terms && 143990b2c210SIan Rogers list_empty(&const_parsed_terms->terms)) { 144063dfcde9SIan Rogers strbuf_addf(&sb, "%s//", pmu->name); 14417a6e9164SIan Rogers } else { 144263dfcde9SIan Rogers strbuf_addf(&sb, "%s/", pmu->name); 144390b2c210SIan Rogers parse_events_terms__to_strbuf(const_parsed_terms, &sb); 14447a6e9164SIan Rogers strbuf_addch(&sb, '/'); 14457a6e9164SIan Rogers } 14467a6e9164SIan Rogers fprintf(stderr, "Attempt to add: %s\n", sb.buf); 14477a6e9164SIan Rogers strbuf_release(&sb); 14487a6e9164SIan Rogers } 14495f537a26SJiri Olsa 14505f537a26SJiri Olsa memset(&attr, 0, sizeof(attr)); 14510197da7aSIan Rogers if (pmu->perf_event_attr_init_default) 14520197da7aSIan Rogers pmu->perf_event_attr_init_default(pmu, &attr); 14530197da7aSIan Rogers 1454c9aeb2e9SIan Rogers attr.type = pmu->type; 14555f537a26SJiri Olsa 145690b2c210SIan Rogers if (!const_parsed_terms || list_empty(&const_parsed_terms->terms)) { 14572b62b3a6SIan Rogers evsel = __add_event(list, &parse_state->idx, &attr, 14582b62b3a6SIan Rogers /*init_attr=*/true, /*name=*/NULL, 14592b62b3a6SIan Rogers /*metric_id=*/NULL, pmu, 14602b62b3a6SIan Rogers /*config_terms=*/NULL, auto_merge_stats, 14612b62b3a6SIan Rogers /*cpu_list=*/NULL); 1462cae256aeSIan Rogers return evsel ? 0 : -ENOMEM; 1463ad962273SAdrian Hunter } 1464ad962273SAdrian Hunter 146590b2c210SIan Rogers parse_events_terms__init(&parsed_terms); 146690b2c210SIan Rogers if (const_parsed_terms) { 146790b2c210SIan Rogers int ret = parse_events_terms__copy(const_parsed_terms, &parsed_terms); 146890b2c210SIan Rogers 146990b2c210SIan Rogers if (ret) 147090b2c210SIan Rogers return ret; 147190b2c210SIan Rogers } 147290b2c210SIan Rogers fix_raw(&parsed_terms, pmu); 147390b2c210SIan Rogers 1474a24d9d9dSIan Rogers /* Configure attr/terms with a known PMU, this will set hardcoded terms. */ 1475a24d9d9dSIan Rogers if (config_attr(&attr, &parsed_terms, parse_state->error, config_term_pmu)) { 1476a24d9d9dSIan Rogers parse_events_terms__exit(&parsed_terms); 1477a24d9d9dSIan Rogers return -EINVAL; 1478a24d9d9dSIan Rogers } 1479a24d9d9dSIan Rogers 1480a24d9d9dSIan Rogers /* Look for event names in the terms and rewrite into format based terms. */ 1481a24d9d9dSIan Rogers if (!parse_state->fake_pmu && perf_pmu__check_alias(pmu, &parsed_terms, 1482a24d9d9dSIan Rogers &info, &alias_rewrote_terms, err)) { 14830d3f0e6fSIan Rogers parse_events_terms__exit(&parsed_terms); 1484a6146d50SZheng Yan return -EINVAL; 1485727adeedSIan Rogers } 1486a6146d50SZheng Yan 14874ac22b48SIan Rogers if (verbose > 1) { 14887a6e9164SIan Rogers struct strbuf sb; 14894ac22b48SIan Rogers 14907a6e9164SIan Rogers strbuf_init(&sb, /*hint=*/ 0); 14910d3f0e6fSIan Rogers parse_events_terms__to_strbuf(&parsed_terms, &sb); 149263dfcde9SIan Rogers fprintf(stderr, "..after resolving event: %s/%s/\n", pmu->name, sb.buf); 14937a6e9164SIan Rogers strbuf_release(&sb); 14944ac22b48SIan Rogers } 14954ac22b48SIan Rogers 1496a24d9d9dSIan Rogers /* Configure attr/terms again if an alias was expanded. */ 1497a24d9d9dSIan Rogers if (alias_rewrote_terms && 1498a24d9d9dSIan Rogers config_attr(&attr, &parsed_terms, parse_state->error, config_term_pmu)) { 14990d3f0e6fSIan Rogers parse_events_terms__exit(&parsed_terms); 1500c056ba6aSJiri Olsa return -EINVAL; 1501727adeedSIan Rogers } 15025f537a26SJiri Olsa 15030d3f0e6fSIan Rogers if (get_config_terms(&parsed_terms, &config_terms)) { 15040d3f0e6fSIan Rogers parse_events_terms__exit(&parsed_terms); 1505930a2e29SJiri Olsa return -ENOMEM; 1506727adeedSIan Rogers } 1507930a2e29SJiri Olsa 1508a1ac7de6SAdrian Hunter /* 1509a1ac7de6SAdrian Hunter * When using default config, record which bits of attr->config were 1510a1ac7de6SAdrian Hunter * changed by the user. 1511a1ac7de6SAdrian Hunter */ 15120197da7aSIan Rogers if (pmu->perf_event_attr_init_default && 15130197da7aSIan Rogers get_config_chgs(pmu, &parsed_terms, &config_terms)) { 15140d3f0e6fSIan Rogers parse_events_terms__exit(&parsed_terms); 1515a1ac7de6SAdrian Hunter return -ENOMEM; 1516727adeedSIan Rogers } 1517a1ac7de6SAdrian Hunter 1518727adeedSIan Rogers if (!parse_state->fake_pmu && 15190d3f0e6fSIan Rogers perf_pmu__config(pmu, &attr, &parsed_terms, parse_state->error)) { 1520a7d212fcSAdrian Hunter free_config_terms(&config_terms); 15210d3f0e6fSIan Rogers parse_events_terms__exit(&parsed_terms); 15225f537a26SJiri Olsa return -EINVAL; 152338f2c422SIan Rogers } 15245f537a26SJiri Olsa 15252b62b3a6SIan Rogers evsel = __add_event(list, &parse_state->idx, &attr, /*init_attr=*/true, 15260d3f0e6fSIan Rogers get_config_name(&parsed_terms), 15270d3f0e6fSIan Rogers get_config_metric_id(&parsed_terms), pmu, 15282b62b3a6SIan Rogers &config_terms, auto_merge_stats, /*cpu_list=*/NULL); 1529727adeedSIan Rogers if (!evsel) { 15300d3f0e6fSIan Rogers parse_events_terms__exit(&parsed_terms); 153133321a06SIan Rogers return -ENOMEM; 1532727adeedSIan Rogers } 153333321a06SIan Rogers 153412279429SJin Yao if (evsel->name) 153512279429SJin Yao evsel->use_config_name = true; 153612279429SJin Yao 153733321a06SIan Rogers evsel->percore = config_term_percore(&evsel->config_terms); 153833321a06SIan Rogers 1539727adeedSIan Rogers if (parse_state->fake_pmu) { 15400d3f0e6fSIan Rogers parse_events_terms__exit(&parsed_terms); 154133321a06SIan Rogers return 0; 1542727adeedSIan Rogers } 154333321a06SIan Rogers 15440d3f0e6fSIan Rogers parse_events_terms__exit(&parsed_terms); 1545b194c9cdSIan Rogers free((char *)evsel->unit); 1546b194c9cdSIan Rogers evsel->unit = strdup(info.unit); 154746441bdcSMatt Fleming evsel->scale = info.scale; 1548044330c1SMatt Fleming evsel->per_pkg = info.per_pkg; 15491d9e446bSJiri Olsa evsel->snapshot = info.snapshot; 155033321a06SIan Rogers return 0; 15515f537a26SJiri Olsa } 15525f537a26SJiri Olsa 15535d9cdc11SArnaldo Carvalho de Melo int parse_events_multi_pmu_add(struct parse_events_state *parse_state, 15544f1b0673SArnaldo Carvalho de Melo const char *event_name, 15550d3f0e6fSIan Rogers const struct parse_events_terms *const_parsed_terms, 155681a4e31fSIan Rogers struct list_head **listp, void *loc_) 15572073ad33SAndi Kleen { 15582073ad33SAndi Kleen struct parse_events_term *term; 1559fb081153SIan Rogers struct list_head *list = NULL; 15602073ad33SAndi Kleen struct perf_pmu *pmu = NULL; 156181a4e31fSIan Rogers YYLTYPE *loc = loc_; 15624f1b0673SArnaldo Carvalho de Melo int ok = 0; 15634f1b0673SArnaldo Carvalho de Melo const char *config; 15640d3f0e6fSIan Rogers struct parse_events_terms parsed_terms; 15652073ad33SAndi Kleen 15662073ad33SAndi Kleen *listp = NULL; 1567fb081153SIan Rogers 15680d3f0e6fSIan Rogers parse_events_terms__init(&parsed_terms); 15690d3f0e6fSIan Rogers if (const_parsed_terms) { 15700d3f0e6fSIan Rogers int ret = parse_events_terms__copy(const_parsed_terms, &parsed_terms); 1571fb081153SIan Rogers 1572727adeedSIan Rogers if (ret) 1573727adeedSIan Rogers return ret; 1574fb081153SIan Rogers } 15758f91662eSIan Rogers 15764f1b0673SArnaldo Carvalho de Melo config = strdup(event_name); 15774f1b0673SArnaldo Carvalho de Melo if (!config) 1578fb081153SIan Rogers goto out_err; 1579fb081153SIan Rogers 1580fb081153SIan Rogers if (parse_events_term__num(&term, 1581fb081153SIan Rogers PARSE_EVENTS__TERM_TYPE_USER, 15824f1b0673SArnaldo Carvalho de Melo config, /*num=*/1, /*novalue=*/true, 158364199ae4SIan Rogers loc, /*loc_val=*/NULL) < 0) { 15844f1b0673SArnaldo Carvalho de Melo zfree(&config); 1585fb081153SIan Rogers goto out_err; 1586fb081153SIan Rogers } 15870d3f0e6fSIan Rogers list_add_tail(&term->list, &parsed_terms.terms); 1588fb081153SIan Rogers 15892073ad33SAndi Kleen /* Add it for all PMUs that support the alias */ 15902073ad33SAndi Kleen list = malloc(sizeof(struct list_head)); 15912073ad33SAndi Kleen if (!list) 1592fb081153SIan Rogers goto out_err; 1593fb081153SIan Rogers 15942073ad33SAndi Kleen INIT_LIST_HEAD(list); 1595fb081153SIan Rogers 15961eaf496eSIan Rogers while ((pmu = perf_pmus__scan(pmu)) != NULL) { 159752c7b4d3SIan Rogers bool auto_merge_stats; 15982073ad33SAndi Kleen 1599411ad22eSIan Rogers if (parse_events__filter_pmu(parse_state, pmu)) 1600411ad22eSIan Rogers continue; 1601411ad22eSIan Rogers 16028f91662eSIan Rogers if (!perf_pmu__have_event(pmu, event_name)) 1603c3245d20SIan Rogers continue; 160452c7b4d3SIan Rogers 1605c3245d20SIan Rogers auto_merge_stats = perf_pmu__auto_merge_stats(pmu); 160663dfcde9SIan Rogers if (!parse_events_add_pmu(parse_state, list, pmu, 160763dfcde9SIan Rogers &parsed_terms, auto_merge_stats)) { 16087a6e9164SIan Rogers struct strbuf sb; 16097a6e9164SIan Rogers 16107a6e9164SIan Rogers strbuf_init(&sb, /*hint=*/ 0); 16110d3f0e6fSIan Rogers parse_events_terms__to_strbuf(&parsed_terms, &sb); 16128f91662eSIan Rogers pr_debug("%s -> %s/%s/\n", event_name, pmu->name, sb.buf); 16137a6e9164SIan Rogers strbuf_release(&sb); 16142073ad33SAndi Kleen ok++; 16152073ad33SAndi Kleen } 1616fb081153SIan Rogers } 1617b4a7276cSJohn Garry 1618b4a7276cSJohn Garry if (parse_state->fake_pmu) { 161963dfcde9SIan Rogers if (!parse_events_add_pmu(parse_state, list, parse_state->fake_pmu, &parsed_terms, 162063dfcde9SIan Rogers /*auto_merge_stats=*/true)) { 16217a6e9164SIan Rogers struct strbuf sb; 16227a6e9164SIan Rogers 16237a6e9164SIan Rogers strbuf_init(&sb, /*hint=*/ 0); 16240d3f0e6fSIan Rogers parse_events_terms__to_strbuf(&parsed_terms, &sb); 16258f91662eSIan Rogers pr_debug("%s -> %s/%s/\n", event_name, "fake_pmu", sb.buf); 16267a6e9164SIan Rogers strbuf_release(&sb); 1627b4a7276cSJohn Garry ok++; 1628b4a7276cSJohn Garry } 1629b4a7276cSJohn Garry } 1630b4a7276cSJohn Garry 1631fb081153SIan Rogers out_err: 16320d3f0e6fSIan Rogers parse_events_terms__exit(&parsed_terms); 1633fb081153SIan Rogers if (ok) 1634fb081153SIan Rogers *listp = list; 1635fb081153SIan Rogers else 1636fb081153SIan Rogers free(list); 16372073ad33SAndi Kleen 1638fb081153SIan Rogers return ok ? 0 : -1; 16392073ad33SAndi Kleen } 16402073ad33SAndi Kleen 16418b734eaaSIan Rogers int parse_events_multi_pmu_add_or_add_pmu(struct parse_events_state *parse_state, 16428b734eaaSIan Rogers const char *event_or_pmu, 16438b734eaaSIan Rogers const struct parse_events_terms *const_parsed_terms, 16448b734eaaSIan Rogers struct list_head **listp, 16458b734eaaSIan Rogers void *loc_) 16468b734eaaSIan Rogers { 16478b734eaaSIan Rogers YYLTYPE *loc = loc_; 164863dfcde9SIan Rogers struct perf_pmu *pmu; 16498b734eaaSIan Rogers int ok = 0; 16508b734eaaSIan Rogers char *help; 16518b734eaaSIan Rogers 16528b734eaaSIan Rogers *listp = malloc(sizeof(**listp)); 16538b734eaaSIan Rogers if (!*listp) 16548b734eaaSIan Rogers return -ENOMEM; 16558b734eaaSIan Rogers 16568b734eaaSIan Rogers INIT_LIST_HEAD(*listp); 16578b734eaaSIan Rogers 16588b734eaaSIan Rogers /* Attempt to add to list assuming event_or_pmu is a PMU name. */ 165963dfcde9SIan Rogers pmu = parse_state->fake_pmu ?: perf_pmus__find(event_or_pmu); 166063dfcde9SIan Rogers if (pmu && !parse_events_add_pmu(parse_state, *listp, pmu, const_parsed_terms, 166163dfcde9SIan Rogers /*auto_merge_stats=*/false)) 16628b734eaaSIan Rogers return 0; 16638b734eaaSIan Rogers 166463dfcde9SIan Rogers pmu = NULL; 16658b734eaaSIan Rogers /* Failed to add, try wildcard expansion of event_or_pmu as a PMU name. */ 16668b734eaaSIan Rogers while ((pmu = perf_pmus__scan(pmu)) != NULL) { 1667f91fa2aeSIan Rogers if (!parse_events__filter_pmu(parse_state, pmu) && 1668f91fa2aeSIan Rogers perf_pmu__match(pmu, event_or_pmu)) { 16698b734eaaSIan Rogers bool auto_merge_stats = perf_pmu__auto_merge_stats(pmu); 16708b734eaaSIan Rogers 167163dfcde9SIan Rogers if (!parse_events_add_pmu(parse_state, *listp, pmu, 16728b734eaaSIan Rogers const_parsed_terms, 167363dfcde9SIan Rogers auto_merge_stats)) { 16748b734eaaSIan Rogers ok++; 16758b734eaaSIan Rogers parse_state->wild_card_pmus = true; 16768b734eaaSIan Rogers } 16778b734eaaSIan Rogers } 16788b734eaaSIan Rogers } 16798b734eaaSIan Rogers if (ok) 16808b734eaaSIan Rogers return 0; 16818b734eaaSIan Rogers 16828b734eaaSIan Rogers /* Failure to add, assume event_or_pmu is an event name. */ 16838b734eaaSIan Rogers zfree(listp); 16844f1b0673SArnaldo Carvalho de Melo if (!parse_events_multi_pmu_add(parse_state, event_or_pmu, const_parsed_terms, listp, loc)) 16858b734eaaSIan Rogers return 0; 16868b734eaaSIan Rogers 16878b734eaaSIan Rogers if (asprintf(&help, "Unable to find PMU or event on a PMU of '%s'", event_or_pmu) < 0) 16888b734eaaSIan Rogers help = NULL; 16898b734eaaSIan Rogers parse_events_error__handle(parse_state->error, loc->first_column, 16908b734eaaSIan Rogers strdup("Bad event or PMU"), 16918b734eaaSIan Rogers help); 16928b734eaaSIan Rogers zfree(listp); 16938b734eaaSIan Rogers return -EINVAL; 16948b734eaaSIan Rogers } 16958b734eaaSIan Rogers 1696347c2f0aSIan Rogers void parse_events__set_leader(char *name, struct list_head *list) 16976a4bb04cSJiri Olsa { 169832dcd021SJiri Olsa struct evsel *leader; 16996a4bb04cSJiri Olsa 1700854f7363SWang Nan if (list_empty(list)) { 1701854f7363SWang Nan WARN_ONCE(true, "WARNING: failed to set leader: empty list"); 1702854f7363SWang Nan return; 1703854f7363SWang Nan } 1704854f7363SWang Nan 1705347c2f0aSIan Rogers leader = list_first_entry(list, struct evsel, core.node); 1706ecdcf630SIan Rogers __perf_evlist__set_leader(list, &leader->core); 1707afd876bbSIan Rogers zfree(&leader->group_name); 17084bb311b2SIan Rogers leader->group_name = name; 170989efb029SJiri Olsa } 171089efb029SJiri Olsa 1711e30a7912SIan Rogers static int parse_events__modifier_list(struct parse_events_state *parse_state, 1712e30a7912SIan Rogers YYLTYPE *loc, 1713e30a7912SIan Rogers struct list_head *list, 1714e30a7912SIan Rogers struct parse_events_modifier mod, 1715e30a7912SIan Rogers bool group) 1716f5b1135bSJiri Olsa { 1717e30a7912SIan Rogers struct evsel *evsel; 1718f5b1135bSJiri Olsa 1719e30a7912SIan Rogers if (!group && mod.weak) { 1720e30a7912SIan Rogers parse_events_error__handle(parse_state->error, loc->first_column, 1721e30a7912SIan Rogers strdup("Weak modifier is for use with groups"), NULL); 1722e30a7912SIan Rogers return -EINVAL; 1723e30a7912SIan Rogers } 1724e30a7912SIan Rogers 1725e30a7912SIan Rogers __evlist__for_each_entry(list, evsel) { 1726e30a7912SIan Rogers /* Translate modifiers into the equivalent evsel excludes. */ 1727e30a7912SIan Rogers int eu = group ? evsel->core.attr.exclude_user : 0; 1728e30a7912SIan Rogers int ek = group ? evsel->core.attr.exclude_kernel : 0; 1729e30a7912SIan Rogers int eh = group ? evsel->core.attr.exclude_hv : 0; 1730e30a7912SIan Rogers int eH = group ? evsel->core.attr.exclude_host : 0; 1731e30a7912SIan Rogers int eG = group ? evsel->core.attr.exclude_guest : 0; 1732f5b1135bSJiri Olsa int exclude = eu | ek | eh; 1733e30a7912SIan Rogers int exclude_GH = group ? evsel->exclude_GH : 0; 1734f5b1135bSJiri Olsa 1735e30a7912SIan Rogers if (mod.precise) { 1736e30a7912SIan Rogers /* use of precise requires exclude_guest */ 1737e30a7912SIan Rogers eG = 1; 1738e30a7912SIan Rogers } 1739e30a7912SIan Rogers if (mod.user) { 1740ab608344SPeter Zijlstra if (!exclude) 1741ab608344SPeter Zijlstra exclude = eu = ek = eh = 1; 1742943b69acSJin Yao if (!exclude_GH && !perf_guest) 1743943b69acSJin Yao eG = 1; 174461c45981SPaul Mackerras eu = 0; 1745e30a7912SIan Rogers } 1746e30a7912SIan Rogers if (mod.kernel) { 1747ab608344SPeter Zijlstra if (!exclude) 1748ab608344SPeter Zijlstra exclude = eu = ek = eh = 1; 174961c45981SPaul Mackerras ek = 0; 1750e30a7912SIan Rogers } 1751e30a7912SIan Rogers if (mod.hypervisor) { 1752ab608344SPeter Zijlstra if (!exclude) 1753ab608344SPeter Zijlstra exclude = eu = ek = eh = 1; 175461c45981SPaul Mackerras eh = 0; 1755e30a7912SIan Rogers } 1756e30a7912SIan Rogers if (mod.guest) { 175799320cc8SJoerg Roedel if (!exclude_GH) 175899320cc8SJoerg Roedel exclude_GH = eG = eH = 1; 175999320cc8SJoerg Roedel eG = 0; 1760e30a7912SIan Rogers } 1761e30a7912SIan Rogers if (mod.host) { 176299320cc8SJoerg Roedel if (!exclude_GH) 176399320cc8SJoerg Roedel exclude_GH = eG = eH = 1; 176499320cc8SJoerg Roedel eH = 0; 176561c45981SPaul Mackerras } 1766e30a7912SIan Rogers evsel->core.attr.exclude_user = eu; 1767e30a7912SIan Rogers evsel->core.attr.exclude_kernel = ek; 1768e30a7912SIan Rogers evsel->core.attr.exclude_hv = eh; 1769e30a7912SIan Rogers evsel->core.attr.exclude_host = eH; 1770e30a7912SIan Rogers evsel->core.attr.exclude_guest = eG; 1771e30a7912SIan Rogers evsel->exclude_GH = exclude_GH; 177274d5b588SJaswinder Singh Rajput 1773e30a7912SIan Rogers /* Simple modifiers copied to the evsel. */ 1774e30a7912SIan Rogers if (mod.precise) { 1775e30a7912SIan Rogers u8 precise = evsel->core.attr.precise_ip + mod.precise; 177686470930SIngo Molnar /* 177789812fc8SJiri Olsa * precise ip: 177889812fc8SJiri Olsa * 177989812fc8SJiri Olsa * 0 - SAMPLE_IP can have arbitrary skid 178089812fc8SJiri Olsa * 1 - SAMPLE_IP must have constant skid 178189812fc8SJiri Olsa * 2 - SAMPLE_IP requested to have 0 skid 178289812fc8SJiri Olsa * 3 - SAMPLE_IP must have 0 skid 178389812fc8SJiri Olsa * 178489812fc8SJiri Olsa * See also PERF_RECORD_MISC_EXACT_IP 178586470930SIngo Molnar */ 1786e30a7912SIan Rogers if (precise > 3) { 1787e30a7912SIan Rogers char *help; 1788e30a7912SIan Rogers 1789e30a7912SIan Rogers if (asprintf(&help, 1790e30a7912SIan Rogers "Maximum combined precise value is 3, adding precision to \"%s\"", 1791e30a7912SIan Rogers evsel__name(evsel)) > 0) { 1792e30a7912SIan Rogers parse_events_error__handle(parse_state->error, 1793e30a7912SIan Rogers loc->first_column, 1794e30a7912SIan Rogers help, NULL); 1795e30a7912SIan Rogers } 179689812fc8SJiri Olsa return -EINVAL; 1797e30a7912SIan Rogers } 1798e30a7912SIan Rogers evsel->core.attr.precise_ip = precise; 1799e30a7912SIan Rogers } 1800e30a7912SIan Rogers if (mod.precise_max) 1801e30a7912SIan Rogers evsel->precise_max = 1; 1802e30a7912SIan Rogers if (mod.non_idle) 1803e30a7912SIan Rogers evsel->core.attr.exclude_idle = 1; 1804e30a7912SIan Rogers if (mod.sample_read) 1805e30a7912SIan Rogers evsel->sample_read = 1; 1806e30a7912SIan Rogers if (mod.pinned && evsel__is_group_leader(evsel)) 1807e30a7912SIan Rogers evsel->core.attr.pinned = 1; 1808e30a7912SIan Rogers if (mod.exclusive && evsel__is_group_leader(evsel)) 1809e30a7912SIan Rogers evsel->core.attr.exclusive = 1; 1810e30a7912SIan Rogers if (mod.weak) 1811e30a7912SIan Rogers evsel->weak_group = true; 1812e30a7912SIan Rogers if (mod.bpf) 1813e30a7912SIan Rogers evsel->bpf_counter = true; 1814e30a7912SIan Rogers } 1815f5b1135bSJiri Olsa return 0; 1816f5b1135bSJiri Olsa } 1817f5b1135bSJiri Olsa 1818e30a7912SIan Rogers int parse_events__modifier_group(struct parse_events_state *parse_state, void *loc, 1819e30a7912SIan Rogers struct list_head *list, 1820e30a7912SIan Rogers struct parse_events_modifier mod) 1821534123f4SJiri Olsa { 1822e30a7912SIan Rogers return parse_events__modifier_list(parse_state, loc, list, mod, /*group=*/true); 1823534123f4SJiri Olsa } 1824534123f4SJiri Olsa 1825e30a7912SIan Rogers int parse_events__modifier_event(struct parse_events_state *parse_state, void *loc, 1826e30a7912SIan Rogers struct list_head *list, 1827e30a7912SIan Rogers struct parse_events_modifier mod) 1828f5b1135bSJiri Olsa { 1829e30a7912SIan Rogers return parse_events__modifier_list(parse_state, loc, list, mod, /*group=*/false); 183086470930SIngo Molnar } 183186470930SIngo Molnar 1832bb65ff78SIan Rogers int parse_events__set_default_name(struct list_head *list, char *name) 1833ac2ba9f3SRobert Richter { 183432dcd021SJiri Olsa struct evsel *evsel; 1835bb65ff78SIan Rogers bool used_name = false; 1836ac2ba9f3SRobert Richter 1837e5cadb93SArnaldo Carvalho de Melo __evlist__for_each_entry(list, evsel) { 18389462e4deSIan Rogers if (!evsel->name) { 1839bb65ff78SIan Rogers evsel->name = used_name ? strdup(name) : name; 1840bb65ff78SIan Rogers used_name = true; 18419462e4deSIan Rogers if (!evsel->name) 18429462e4deSIan Rogers return -ENOMEM; 18439462e4deSIan Rogers } 1844ac2ba9f3SRobert Richter } 1845bb65ff78SIan Rogers if (!used_name) 1846bb65ff78SIan Rogers free(name); 1847ac2ba9f3SRobert Richter return 0; 1848ac2ba9f3SRobert Richter } 1849ac2ba9f3SRobert Richter 18501244a327SJiri Olsa static int parse_events__scanner(const char *str, 1851edb217ffSIan Rogers FILE *input, 18521244a327SJiri Olsa struct parse_events_state *parse_state) 1853ac20de6fSZheng Yan { 1854ac20de6fSZheng Yan YY_BUFFER_STATE buffer; 1855ac20de6fSZheng Yan void *scanner; 1856ac20de6fSZheng Yan int ret; 1857ac20de6fSZheng Yan 18581244a327SJiri Olsa ret = parse_events_lex_init_extra(parse_state, &scanner); 1859ac20de6fSZheng Yan if (ret) 1860ac20de6fSZheng Yan return ret; 1861ac20de6fSZheng Yan 1862edb217ffSIan Rogers if (str) 1863ac20de6fSZheng Yan buffer = parse_events__scan_string(str, scanner); 1864edb217ffSIan Rogers else 1865edb217ffSIan Rogers parse_events_set_in(input, scanner); 1866ac20de6fSZheng Yan 1867ac20de6fSZheng Yan #ifdef PARSER_DEBUG 1868ac20de6fSZheng Yan parse_events_debug = 1; 1869ae762641SJiri Olsa parse_events_set_debug(1, scanner); 1870ac20de6fSZheng Yan #endif 18715d9cdc11SArnaldo Carvalho de Melo ret = parse_events_parse(parse_state, scanner); 1872ac20de6fSZheng Yan 1873edb217ffSIan Rogers if (str) { 1874ac20de6fSZheng Yan parse_events__flush_buffer(buffer, scanner); 1875ac20de6fSZheng Yan parse_events__delete_buffer(buffer, scanner); 1876edb217ffSIan Rogers } 1877ac20de6fSZheng Yan parse_events_lex_destroy(scanner); 1878ac20de6fSZheng Yan return ret; 1879ac20de6fSZheng Yan } 1880ac20de6fSZheng Yan 188190e2b22dSJiri Olsa /* 188290e2b22dSJiri Olsa * parse event config string, return a list of event terms. 188390e2b22dSJiri Olsa */ 18840d3f0e6fSIan Rogers int parse_events_terms(struct parse_events_terms *terms, const char *str, FILE *input) 188590e2b22dSJiri Olsa { 18865d9cdc11SArnaldo Carvalho de Melo struct parse_events_state parse_state = { 188790e2b22dSJiri Olsa .terms = NULL, 18881244a327SJiri Olsa .stoken = PE_START_TERMS, 188990e2b22dSJiri Olsa }; 189090e2b22dSJiri Olsa int ret; 189190e2b22dSJiri Olsa 1892edb217ffSIan Rogers ret = parse_events__scanner(str, input, &parse_state); 18930d3f0e6fSIan Rogers if (!ret) 18940d3f0e6fSIan Rogers list_splice(&parse_state.terms->terms, &terms->terms); 18954929e95aSJiri Olsa 18965d9cdc11SArnaldo Carvalho de Melo zfree(&parse_state.terms); 189790e2b22dSJiri Olsa return ret; 189890e2b22dSJiri Olsa } 189990e2b22dSJiri Olsa 1900a90cc5a9SIan Rogers static int evsel__compute_group_pmu_name(struct evsel *evsel, 1901a90cc5a9SIan Rogers const struct list_head *head) 1902a90cc5a9SIan Rogers { 1903a90cc5a9SIan Rogers struct evsel *leader = evsel__leader(evsel); 1904a90cc5a9SIan Rogers struct evsel *pos; 1905251aa040SIan Rogers const char *group_pmu_name; 1906251aa040SIan Rogers struct perf_pmu *pmu = evsel__find_pmu(evsel); 1907a90cc5a9SIan Rogers 1908251aa040SIan Rogers if (!pmu) { 1909251aa040SIan Rogers /* 1910251aa040SIan Rogers * For PERF_TYPE_HARDWARE and PERF_TYPE_HW_CACHE types the PMU 1911251aa040SIan Rogers * is a core PMU, but in heterogeneous systems this is 1912251aa040SIan Rogers * unknown. For now pick the first core PMU. 1913251aa040SIan Rogers */ 1914251aa040SIan Rogers pmu = perf_pmus__scan_core(NULL); 1915251aa040SIan Rogers } 1916251aa040SIan Rogers if (!pmu) { 1917bc06026dSYang Jihong pr_debug("No PMU found for '%s'\n", evsel__name(evsel)); 1918251aa040SIan Rogers return -EINVAL; 1919251aa040SIan Rogers } 1920251aa040SIan Rogers group_pmu_name = pmu->name; 1921a90cc5a9SIan Rogers /* 1922a90cc5a9SIan Rogers * Software events may be in a group with other uncore PMU events. Use 1923a90cc5a9SIan Rogers * the pmu_name of the first non-software event to avoid breaking the 1924a90cc5a9SIan Rogers * software event out of the group. 1925a90cc5a9SIan Rogers * 1926a90cc5a9SIan Rogers * Aux event leaders, like intel_pt, expect a group with events from 1927a90cc5a9SIan Rogers * other PMUs, so substitute the AUX event's PMU in this case. 1928a90cc5a9SIan Rogers */ 1929251aa040SIan Rogers if (perf_pmu__is_software(pmu) || evsel__is_aux_event(leader)) { 1930251aa040SIan Rogers struct perf_pmu *leader_pmu = evsel__find_pmu(leader); 1931251aa040SIan Rogers 1932251aa040SIan Rogers if (!leader_pmu) { 1933251aa040SIan Rogers /* As with determining pmu above. */ 1934251aa040SIan Rogers leader_pmu = perf_pmus__scan_core(NULL); 1935251aa040SIan Rogers } 1936a90cc5a9SIan Rogers /* 1937a90cc5a9SIan Rogers * Starting with the leader, find the first event with a named 1938251aa040SIan Rogers * non-software PMU. for_each_group_(member|evsel) isn't used as 1939251aa040SIan Rogers * the list isn't yet sorted putting evsel's in the same group 1940251aa040SIan Rogers * together. 1941a90cc5a9SIan Rogers */ 1942251aa040SIan Rogers if (leader_pmu && !perf_pmu__is_software(leader_pmu)) { 1943251aa040SIan Rogers group_pmu_name = leader_pmu->name; 1944a90cc5a9SIan Rogers } else if (leader->core.nr_members > 1) { 1945a90cc5a9SIan Rogers list_for_each_entry(pos, head, core.node) { 1946251aa040SIan Rogers struct perf_pmu *pos_pmu; 1947251aa040SIan Rogers 1948251aa040SIan Rogers if (pos == leader || evsel__leader(pos) != leader) 1949251aa040SIan Rogers continue; 1950251aa040SIan Rogers pos_pmu = evsel__find_pmu(pos); 1951251aa040SIan Rogers if (!pos_pmu) { 1952251aa040SIan Rogers /* As with determining pmu above. */ 1953251aa040SIan Rogers pos_pmu = perf_pmus__scan_core(NULL); 1954251aa040SIan Rogers } 1955251aa040SIan Rogers if (pos_pmu && !perf_pmu__is_software(pos_pmu)) { 1956251aa040SIan Rogers group_pmu_name = pos_pmu->name; 1957a90cc5a9SIan Rogers break; 1958a90cc5a9SIan Rogers } 1959a90cc5a9SIan Rogers } 1960a90cc5a9SIan Rogers } 1961a90cc5a9SIan Rogers } 1962251aa040SIan Rogers /* Assign the actual name taking care that the fake PMU lacks a name. */ 1963251aa040SIan Rogers evsel->group_pmu_name = strdup(group_pmu_name ?: "fake"); 1964a90cc5a9SIan Rogers return evsel->group_pmu_name ? 0 : -ENOMEM; 1965a90cc5a9SIan Rogers } 1966a90cc5a9SIan Rogers 1967347c2f0aSIan Rogers __weak int arch_evlist__cmp(const struct evsel *lhs, const struct evsel *rhs) 1968347c2f0aSIan Rogers { 1969347c2f0aSIan Rogers /* Order by insertion index. */ 1970347c2f0aSIan Rogers return lhs->core.idx - rhs->core.idx; 1971347c2f0aSIan Rogers } 1972347c2f0aSIan Rogers 1973b161f25fSIan Rogers static int evlist__cmp(void *_fg_idx, const struct list_head *l, const struct list_head *r) 1974347c2f0aSIan Rogers { 1975347c2f0aSIan Rogers const struct perf_evsel *lhs_core = container_of(l, struct perf_evsel, node); 1976347c2f0aSIan Rogers const struct evsel *lhs = container_of(lhs_core, struct evsel, core); 1977347c2f0aSIan Rogers const struct perf_evsel *rhs_core = container_of(r, struct perf_evsel, node); 1978347c2f0aSIan Rogers const struct evsel *rhs = container_of(rhs_core, struct evsel, core); 1979b161f25fSIan Rogers int *force_grouped_idx = _fg_idx; 1980b161f25fSIan Rogers int lhs_sort_idx, rhs_sort_idx, ret; 1981347c2f0aSIan Rogers const char *lhs_pmu_name, *rhs_pmu_name; 1982b161f25fSIan Rogers bool lhs_has_group, rhs_has_group; 1983347c2f0aSIan Rogers 1984347c2f0aSIan Rogers /* 1985347c2f0aSIan Rogers * First sort by grouping/leader. Read the leader idx only if the evsel 1986a90cc5a9SIan Rogers * is part of a group, by default ungrouped events will be sorted 1987a90cc5a9SIan Rogers * relative to grouped events based on where the first ungrouped event 1988a90cc5a9SIan Rogers * occurs. If both events don't have a group we want to fall-through to 1989a90cc5a9SIan Rogers * the arch specific sorting, that can reorder and fix things like 1990a90cc5a9SIan Rogers * Intel's topdown events. 1991347c2f0aSIan Rogers */ 1992327daf34SIan Rogers if (lhs_core->leader != lhs_core || lhs_core->nr_members > 1) { 1993327daf34SIan Rogers lhs_has_group = true; 1994b161f25fSIan Rogers lhs_sort_idx = lhs_core->leader->idx; 1995b161f25fSIan Rogers } else { 1996b161f25fSIan Rogers lhs_has_group = false; 1997b161f25fSIan Rogers lhs_sort_idx = *force_grouped_idx != -1 && arch_evsel__must_be_in_group(lhs) 1998b161f25fSIan Rogers ? *force_grouped_idx 1999b161f25fSIan Rogers : lhs_core->idx; 2000327daf34SIan Rogers } 2001327daf34SIan Rogers if (rhs_core->leader != rhs_core || rhs_core->nr_members > 1) { 2002327daf34SIan Rogers rhs_has_group = true; 2003b161f25fSIan Rogers rhs_sort_idx = rhs_core->leader->idx; 2004b161f25fSIan Rogers } else { 2005b161f25fSIan Rogers rhs_has_group = false; 2006b161f25fSIan Rogers rhs_sort_idx = *force_grouped_idx != -1 && arch_evsel__must_be_in_group(rhs) 2007b161f25fSIan Rogers ? *force_grouped_idx 2008b161f25fSIan Rogers : rhs_core->idx; 2009327daf34SIan Rogers } 2010347c2f0aSIan Rogers 2011b161f25fSIan Rogers if (lhs_sort_idx != rhs_sort_idx) 2012b161f25fSIan Rogers return lhs_sort_idx - rhs_sort_idx; 2013347c2f0aSIan Rogers 2014327daf34SIan Rogers /* Group by PMU if there is a group. Groups can't span PMUs. */ 2015327daf34SIan Rogers if (lhs_has_group && rhs_has_group) { 2016a90cc5a9SIan Rogers lhs_pmu_name = lhs->group_pmu_name; 2017a90cc5a9SIan Rogers rhs_pmu_name = rhs->group_pmu_name; 2018347c2f0aSIan Rogers ret = strcmp(lhs_pmu_name, rhs_pmu_name); 2019347c2f0aSIan Rogers if (ret) 2020347c2f0aSIan Rogers return ret; 2021327daf34SIan Rogers } 2022347c2f0aSIan Rogers 2023347c2f0aSIan Rogers /* Architecture specific sorting. */ 2024347c2f0aSIan Rogers return arch_evlist__cmp(lhs, rhs); 2025347c2f0aSIan Rogers } 2026347c2f0aSIan Rogers 2027a90cc5a9SIan Rogers static int parse_events__sort_events_and_fix_groups(struct list_head *list) 2028347c2f0aSIan Rogers { 2029b161f25fSIan Rogers int idx = 0, force_grouped_idx = -1; 2030347c2f0aSIan Rogers struct evsel *pos, *cur_leader = NULL; 2031347c2f0aSIan Rogers struct perf_evsel *cur_leaders_grp = NULL; 20325c49b6c3SIan Rogers bool idx_changed = false, cur_leader_force_grouped = false; 2033a4c7d7c5SIan Rogers int orig_num_leaders = 0, num_leaders = 0; 2034a90cc5a9SIan Rogers int ret; 2035347c2f0aSIan Rogers 2036347c2f0aSIan Rogers /* 2037347c2f0aSIan Rogers * Compute index to insert ungrouped events at. Place them where the 2038347c2f0aSIan Rogers * first ungrouped event appears. 2039347c2f0aSIan Rogers */ 2040347c2f0aSIan Rogers list_for_each_entry(pos, list, core.node) { 2041347c2f0aSIan Rogers const struct evsel *pos_leader = evsel__leader(pos); 2042347c2f0aSIan Rogers 2043a90cc5a9SIan Rogers ret = evsel__compute_group_pmu_name(pos, list); 2044a90cc5a9SIan Rogers if (ret) 2045a90cc5a9SIan Rogers return ret; 2046a90cc5a9SIan Rogers 2047a4c7d7c5SIan Rogers if (pos == pos_leader) 2048a4c7d7c5SIan Rogers orig_num_leaders++; 2049347c2f0aSIan Rogers 2050a4c7d7c5SIan Rogers /* 2051a4c7d7c5SIan Rogers * Ensure indexes are sequential, in particular for multiple 2052a4c7d7c5SIan Rogers * event lists being merged. The indexes are used to detect when 2053a4c7d7c5SIan Rogers * the user order is modified. 2054a4c7d7c5SIan Rogers */ 2055a4c7d7c5SIan Rogers pos->core.idx = idx++; 2056a4c7d7c5SIan Rogers 2057b161f25fSIan Rogers /* Remember an index to sort all forced grouped events together to. */ 2058b161f25fSIan Rogers if (force_grouped_idx == -1 && pos == pos_leader && pos->core.nr_members < 2 && 2059b161f25fSIan Rogers arch_evsel__must_be_in_group(pos)) 2060b161f25fSIan Rogers force_grouped_idx = pos->core.idx; 2061347c2f0aSIan Rogers } 2062347c2f0aSIan Rogers 2063347c2f0aSIan Rogers /* Sort events. */ 2064b161f25fSIan Rogers list_sort(&force_grouped_idx, list, evlist__cmp); 2065347c2f0aSIan Rogers 2066347c2f0aSIan Rogers /* 2067347c2f0aSIan Rogers * Recompute groups, splitting for PMUs and adding groups for events 2068347c2f0aSIan Rogers * that require them. 2069347c2f0aSIan Rogers */ 2070347c2f0aSIan Rogers idx = 0; 2071347c2f0aSIan Rogers list_for_each_entry(pos, list, core.node) { 2072347c2f0aSIan Rogers const struct evsel *pos_leader = evsel__leader(pos); 2073a90cc5a9SIan Rogers const char *pos_pmu_name = pos->group_pmu_name; 2074e8d38345SIan Rogers const char *cur_leader_pmu_name; 2075b161f25fSIan Rogers bool pos_force_grouped = force_grouped_idx != -1 && 2076b161f25fSIan Rogers arch_evsel__must_be_in_group(pos); 2077347c2f0aSIan Rogers 2078347c2f0aSIan Rogers /* Reset index and nr_members. */ 2079a4c7d7c5SIan Rogers if (pos->core.idx != idx) 2080a4c7d7c5SIan Rogers idx_changed = true; 2081347c2f0aSIan Rogers pos->core.idx = idx++; 2082347c2f0aSIan Rogers pos->core.nr_members = 0; 2083347c2f0aSIan Rogers 2084347c2f0aSIan Rogers /* 2085347c2f0aSIan Rogers * Set the group leader respecting the given groupings and that 2086347c2f0aSIan Rogers * groups can't span PMUs. 2087347c2f0aSIan Rogers */ 2088347c2f0aSIan Rogers if (!cur_leader) 2089347c2f0aSIan Rogers cur_leader = pos; 2090347c2f0aSIan Rogers 2091a90cc5a9SIan Rogers cur_leader_pmu_name = cur_leader->group_pmu_name; 20925c49b6c3SIan Rogers if ((cur_leaders_grp != pos->core.leader && 20935c49b6c3SIan Rogers (!pos_force_grouped || !cur_leader_force_grouped)) || 2094347c2f0aSIan Rogers strcmp(cur_leader_pmu_name, pos_pmu_name)) { 2095347c2f0aSIan Rogers /* Event is for a different group/PMU than last. */ 2096347c2f0aSIan Rogers cur_leader = pos; 2097347c2f0aSIan Rogers /* 2098347c2f0aSIan Rogers * Remember the leader's group before it is overwritten, 2099347c2f0aSIan Rogers * so that later events match as being in the same 2100347c2f0aSIan Rogers * group. 2101347c2f0aSIan Rogers */ 2102347c2f0aSIan Rogers cur_leaders_grp = pos->core.leader; 2103347c2f0aSIan Rogers /* 21045c49b6c3SIan Rogers * Avoid forcing events into groups with events that 21055c49b6c3SIan Rogers * don't need to be in the group. 2106347c2f0aSIan Rogers */ 21075c49b6c3SIan Rogers cur_leader_force_grouped = pos_force_grouped; 2108347c2f0aSIan Rogers } 2109e8d38345SIan Rogers if (pos_leader != cur_leader) { 2110e8d38345SIan Rogers /* The leader changed so update it. */ 2111347c2f0aSIan Rogers evsel__set_leader(pos, cur_leader); 2112347c2f0aSIan Rogers } 2113347c2f0aSIan Rogers } 2114347c2f0aSIan Rogers list_for_each_entry(pos, list, core.node) { 2115a4c7d7c5SIan Rogers struct evsel *pos_leader = evsel__leader(pos); 2116a4c7d7c5SIan Rogers 2117a4c7d7c5SIan Rogers if (pos == pos_leader) 2118a4c7d7c5SIan Rogers num_leaders++; 2119a4c7d7c5SIan Rogers pos_leader->core.nr_members++; 2120347c2f0aSIan Rogers } 2121a90cc5a9SIan Rogers return (idx_changed || num_leaders != orig_num_leaders) ? 1 : 0; 2122347c2f0aSIan Rogers } 2123347c2f0aSIan Rogers 2124411ad22eSIan Rogers int __parse_events(struct evlist *evlist, const char *str, const char *pmu_filter, 2125a4c7d7c5SIan Rogers struct parse_events_error *err, struct perf_pmu *fake_pmu, 2126a2a6604eSDominique Martinet bool warn_if_reordered, bool fake_tp) 212786470930SIngo Molnar { 21285d9cdc11SArnaldo Carvalho de Melo struct parse_events_state parse_state = { 21295d9cdc11SArnaldo Carvalho de Melo .list = LIST_HEAD_INIT(parse_state.list), 21306484d2f9SJiri Olsa .idx = evlist->core.nr_entries, 2131b39b8393SJiri Olsa .error = err, 21321244a327SJiri Olsa .stoken = PE_START_EVENTS, 21333bf91aa5SArnaldo Carvalho de Melo .fake_pmu = fake_pmu, 2134a2a6604eSDominique Martinet .fake_tp = fake_tp, 2135411ad22eSIan Rogers .pmu_filter = pmu_filter, 21366fd1e519SIan Rogers .match_legacy_cache_terms = true, 213746010ab2SJiri Olsa }; 2138a90cc5a9SIan Rogers int ret, ret2; 213986470930SIngo Molnar 2140edb217ffSIan Rogers ret = parse_events__scanner(str, /*input=*/ NULL, &parse_state); 214115bfd2ccSWang Nan 21428e8714c3SIan Rogers if (!ret && list_empty(&parse_state.list)) { 2143c23080a6SArnaldo Carvalho de Melo WARN_ONCE(true, "WARNING: event parser found nothing\n"); 2144854f7363SWang Nan return -1; 2145854f7363SWang Nan } 2146854f7363SWang Nan 2147a90cc5a9SIan Rogers ret2 = parse_events__sort_events_and_fix_groups(&parse_state.list); 2148a90cc5a9SIan Rogers if (ret2 < 0) 2149a90cc5a9SIan Rogers return ret; 2150a90cc5a9SIan Rogers 2151a90cc5a9SIan Rogers if (ret2 && warn_if_reordered && !parse_state.wild_card_pmus) 2152a4c7d7c5SIan Rogers pr_warning("WARNING: events were regrouped to match PMUs\n"); 2153347c2f0aSIan Rogers 21548e8714c3SIan Rogers /* 21558e8714c3SIan Rogers * Add list to the evlist even with errors to allow callers to clean up. 21568e8714c3SIan Rogers */ 2157e414fd1aSArnaldo Carvalho de Melo evlist__splice_list_tail(evlist, &parse_state.list); 21588e8714c3SIan Rogers 21598e8714c3SIan Rogers if (!ret) { 21608e8714c3SIan Rogers struct evsel *last; 21618e8714c3SIan Rogers 2162515dbe48SJiri Olsa last = evlist__last(evlist); 216315bfd2ccSWang Nan last->cmdline_group_boundary = true; 216415bfd2ccSWang Nan 216586470930SIngo Molnar return 0; 216686470930SIngo Molnar } 216786470930SIngo Molnar 21685d7be90eSJiri Olsa /* 21695d7be90eSJiri Olsa * There are 2 users - builtin-record and builtin-test objects. 2170c12995a5SJiri Olsa * Both call evlist__delete in case of error, so we dont 21715d7be90eSJiri Olsa * need to bother. 21725d7be90eSJiri Olsa */ 217389812fc8SJiri Olsa return ret; 217489812fc8SJiri Olsa } 217589812fc8SJiri Olsa 2176806731a9SAdrian Hunter int parse_event(struct evlist *evlist, const char *str) 2177806731a9SAdrian Hunter { 2178806731a9SAdrian Hunter struct parse_events_error err; 2179806731a9SAdrian Hunter int ret; 2180806731a9SAdrian Hunter 2181806731a9SAdrian Hunter parse_events_error__init(&err); 2182806731a9SAdrian Hunter ret = parse_events(evlist, str, &err); 2183806731a9SAdrian Hunter parse_events_error__exit(&err); 2184806731a9SAdrian Hunter return ret; 2185806731a9SAdrian Hunter } 2186806731a9SAdrian Hunter 2187fd7b8e8fSIan Rogers struct parse_events_error_entry { 2188fd7b8e8fSIan Rogers /** @list: The list the error is part of. */ 2189fd7b8e8fSIan Rogers struct list_head list; 2190fd7b8e8fSIan Rogers /** @idx: index in the parsed string */ 2191fd7b8e8fSIan Rogers int idx; 2192fd7b8e8fSIan Rogers /** @str: string to display at the index */ 2193fd7b8e8fSIan Rogers char *str; 2194fd7b8e8fSIan Rogers /** @help: optional help string */ 2195fd7b8e8fSIan Rogers char *help; 2196fd7b8e8fSIan Rogers }; 2197fd7b8e8fSIan Rogers 219807eafd4eSIan Rogers void parse_events_error__init(struct parse_events_error *err) 219907eafd4eSIan Rogers { 2200fd7b8e8fSIan Rogers INIT_LIST_HEAD(&err->list); 220107eafd4eSIan Rogers } 220207eafd4eSIan Rogers 220307eafd4eSIan Rogers void parse_events_error__exit(struct parse_events_error *err) 220407eafd4eSIan Rogers { 2205fd7b8e8fSIan Rogers struct parse_events_error_entry *pos, *tmp; 2206fd7b8e8fSIan Rogers 2207fd7b8e8fSIan Rogers list_for_each_entry_safe(pos, tmp, &err->list, list) { 2208fd7b8e8fSIan Rogers zfree(&pos->str); 2209fd7b8e8fSIan Rogers zfree(&pos->help); 2210fd7b8e8fSIan Rogers list_del_init(&pos->list); 2211fd7b8e8fSIan Rogers free(pos); 2212fd7b8e8fSIan Rogers } 221307eafd4eSIan Rogers } 221407eafd4eSIan Rogers 22156c191289SIan Rogers void parse_events_error__handle(struct parse_events_error *err, int idx, 22166c191289SIan Rogers char *str, char *help) 22176c191289SIan Rogers { 2218fd7b8e8fSIan Rogers struct parse_events_error_entry *entry; 2219fd7b8e8fSIan Rogers 2220806731a9SAdrian Hunter if (WARN(!str || !err, "WARNING: failed to provide error string or struct\n")) 22212e828582SAdrian Hunter goto out_free; 22222e828582SAdrian Hunter 2223fd7b8e8fSIan Rogers entry = zalloc(sizeof(*entry)); 2224fd7b8e8fSIan Rogers if (!entry) { 2225fd7b8e8fSIan Rogers pr_err("Failed to allocate memory for event parsing error: %s (%s)\n", 2226fd7b8e8fSIan Rogers str, help ?: "<no help>"); 2227fd7b8e8fSIan Rogers goto out_free; 2228fd7b8e8fSIan Rogers } 2229fd7b8e8fSIan Rogers entry->idx = idx; 2230fd7b8e8fSIan Rogers entry->str = str; 2231fd7b8e8fSIan Rogers entry->help = help; 2232fd7b8e8fSIan Rogers list_add(&entry->list, &err->list); 2233fd7b8e8fSIan Rogers return; 22342e828582SAdrian Hunter out_free: 22352e828582SAdrian Hunter free(str); 22362e828582SAdrian Hunter free(help); 22376c191289SIan Rogers } 22386c191289SIan Rogers 2239b39b8393SJiri Olsa #define MAX_WIDTH 1000 2240b39b8393SJiri Olsa static int get_term_width(void) 2241b39b8393SJiri Olsa { 2242b39b8393SJiri Olsa struct winsize ws; 2243b39b8393SJiri Olsa 2244b39b8393SJiri Olsa get_term_dimensions(&ws); 2245b39b8393SJiri Olsa return ws.ws_col > MAX_WIDTH ? MAX_WIDTH : ws.ws_col; 2246b39b8393SJiri Olsa } 2247b39b8393SJiri Olsa 22486c191289SIan Rogers static void __parse_events_error__print(int err_idx, const char *err_str, 2249a910e466SIan Rogers const char *err_help, const char *event) 2250b39b8393SJiri Olsa { 2251b39b8393SJiri Olsa const char *str = "invalid or unsupported event: "; 2252b39b8393SJiri Olsa char _buf[MAX_WIDTH]; 2253b39b8393SJiri Olsa char *buf = (char *) event; 2254b39b8393SJiri Olsa int idx = 0; 2255a910e466SIan Rogers if (err_str) { 2256b39b8393SJiri Olsa /* -2 for extra '' in the final fprintf */ 2257b39b8393SJiri Olsa int width = get_term_width() - 2; 2258b39b8393SJiri Olsa int len_event = strlen(event); 2259b39b8393SJiri Olsa int len_str, max_len, cut = 0; 2260b39b8393SJiri Olsa 2261b39b8393SJiri Olsa /* 2262b39b8393SJiri Olsa * Maximum error index indent, we will cut 2263b39b8393SJiri Olsa * the event string if it's bigger. 2264b39b8393SJiri Olsa */ 2265141b2d31SAdrian Hunter int max_err_idx = 13; 2266b39b8393SJiri Olsa 2267b39b8393SJiri Olsa /* 2268b39b8393SJiri Olsa * Let's be specific with the message when 2269b39b8393SJiri Olsa * we have the precise error. 2270b39b8393SJiri Olsa */ 2271b39b8393SJiri Olsa str = "event syntax error: "; 2272b39b8393SJiri Olsa len_str = strlen(str); 2273b39b8393SJiri Olsa max_len = width - len_str; 2274b39b8393SJiri Olsa 2275b39b8393SJiri Olsa buf = _buf; 2276b39b8393SJiri Olsa 2277bd1a0be5SAdam Buchbinder /* We're cutting from the beginning. */ 2278a910e466SIan Rogers if (err_idx > max_err_idx) 2279a910e466SIan Rogers cut = err_idx - max_err_idx; 2280b39b8393SJiri Olsa 2281b39b8393SJiri Olsa strncpy(buf, event + cut, max_len); 2282b39b8393SJiri Olsa 2283b39b8393SJiri Olsa /* Mark cut parts with '..' on both sides. */ 2284b39b8393SJiri Olsa if (cut) 2285b39b8393SJiri Olsa buf[0] = buf[1] = '.'; 2286b39b8393SJiri Olsa 2287b39b8393SJiri Olsa if ((len_event - cut) > max_len) { 2288b39b8393SJiri Olsa buf[max_len - 1] = buf[max_len - 2] = '.'; 2289b39b8393SJiri Olsa buf[max_len] = 0; 2290b39b8393SJiri Olsa } 2291b39b8393SJiri Olsa 2292a910e466SIan Rogers idx = len_str + err_idx - cut; 2293b39b8393SJiri Olsa } 2294b39b8393SJiri Olsa 2295b39b8393SJiri Olsa fprintf(stderr, "%s'%s'\n", str, buf); 2296b39b8393SJiri Olsa if (idx) { 2297a910e466SIan Rogers fprintf(stderr, "%*s\\___ %s\n", idx + 1, "", err_str); 2298a910e466SIan Rogers if (err_help) 2299a910e466SIan Rogers fprintf(stderr, "\n%s\n", err_help); 2300a910e466SIan Rogers } 2301a910e466SIan Rogers } 2302a910e466SIan Rogers 2303fd7b8e8fSIan Rogers void parse_events_error__print(const struct parse_events_error *err, 2304a910e466SIan Rogers const char *event) 2305a910e466SIan Rogers { 2306fd7b8e8fSIan Rogers struct parse_events_error_entry *pos; 2307fd7b8e8fSIan Rogers bool first = true; 2308a910e466SIan Rogers 2309fd7b8e8fSIan Rogers list_for_each_entry(pos, &err->list, list) { 2310fd7b8e8fSIan Rogers if (!first) 2311fd7b8e8fSIan Rogers fputs("\n", stderr); 2312fd7b8e8fSIan Rogers __parse_events_error__print(pos->idx, pos->str, pos->help, event); 2313fd7b8e8fSIan Rogers first = false; 2314b39b8393SJiri Olsa } 2315b39b8393SJiri Olsa } 2316b39b8393SJiri Olsa 2317fd7b8e8fSIan Rogers /* 2318fd7b8e8fSIan Rogers * In the list of errors err, do any of the error strings (str) contain the 2319fd7b8e8fSIan Rogers * given needle string? 2320fd7b8e8fSIan Rogers */ 2321fd7b8e8fSIan Rogers bool parse_events_error__contains(const struct parse_events_error *err, 2322fd7b8e8fSIan Rogers const char *needle) 2323fd7b8e8fSIan Rogers { 2324fd7b8e8fSIan Rogers struct parse_events_error_entry *pos; 2325fd7b8e8fSIan Rogers 2326fd7b8e8fSIan Rogers list_for_each_entry(pos, &err->list, list) { 2327fd7b8e8fSIan Rogers if (strstr(pos->str, needle) != NULL) 2328fd7b8e8fSIan Rogers return true; 2329fd7b8e8fSIan Rogers } 2330fd7b8e8fSIan Rogers return false; 2331fd7b8e8fSIan Rogers } 2332fd7b8e8fSIan Rogers 2333b39b8393SJiri Olsa #undef MAX_WIDTH 2334b39b8393SJiri Olsa 2335f120f9d5SJiri Olsa int parse_events_option(const struct option *opt, const char *str, 23361d037ca1SIrina Tirdea int unset __maybe_unused) 2337f120f9d5SJiri Olsa { 2338411ad22eSIan Rogers struct parse_events_option_args *args = opt->value; 2339a910e466SIan Rogers struct parse_events_error err; 2340a910e466SIan Rogers int ret; 2341a910e466SIan Rogers 234207eafd4eSIan Rogers parse_events_error__init(&err); 2343411ad22eSIan Rogers ret = __parse_events(*args->evlistp, str, args->pmu_filter, &err, 2344a2a6604eSDominique Martinet /*fake_pmu=*/NULL, /*warn_if_reordered=*/true, 2345a2a6604eSDominique Martinet /*fake_tp=*/false); 23469175ce1fSAndi Kleen 2347333b5665SAndi Kleen if (ret) { 23486c191289SIan Rogers parse_events_error__print(&err, str); 2349333b5665SAndi Kleen fprintf(stderr, "Run 'perf list' for a list of valid events\n"); 2350333b5665SAndi Kleen } 235107eafd4eSIan Rogers parse_events_error__exit(&err); 2352b39b8393SJiri Olsa 23539175ce1fSAndi Kleen return ret; 2354f120f9d5SJiri Olsa } 2355f120f9d5SJiri Olsa 2356d0abbc3cSArnaldo Carvalho de Melo int parse_events_option_new_evlist(const struct option *opt, const char *str, int unset) 2357d0abbc3cSArnaldo Carvalho de Melo { 2358411ad22eSIan Rogers struct parse_events_option_args *args = opt->value; 2359d0abbc3cSArnaldo Carvalho de Melo int ret; 2360d0abbc3cSArnaldo Carvalho de Melo 2361411ad22eSIan Rogers if (*args->evlistp == NULL) { 2362411ad22eSIan Rogers *args->evlistp = evlist__new(); 2363d0abbc3cSArnaldo Carvalho de Melo 2364411ad22eSIan Rogers if (*args->evlistp == NULL) { 2365d0abbc3cSArnaldo Carvalho de Melo fprintf(stderr, "Not enough memory to create evlist\n"); 2366d0abbc3cSArnaldo Carvalho de Melo return -1; 2367d0abbc3cSArnaldo Carvalho de Melo } 2368d0abbc3cSArnaldo Carvalho de Melo } 2369d0abbc3cSArnaldo Carvalho de Melo ret = parse_events_option(opt, str, unset); 2370d0abbc3cSArnaldo Carvalho de Melo if (ret) { 2371411ad22eSIan Rogers evlist__delete(*args->evlistp); 2372411ad22eSIan Rogers *args->evlistp = NULL; 2373d0abbc3cSArnaldo Carvalho de Melo } 2374d0abbc3cSArnaldo Carvalho de Melo 2375d0abbc3cSArnaldo Carvalho de Melo return ret; 2376d0abbc3cSArnaldo Carvalho de Melo } 2377d0abbc3cSArnaldo Carvalho de Melo 23784ba1faa1SWang Nan static int 237963503dbaSJiri Olsa foreach_evsel_in_last_glob(struct evlist *evlist, 238032dcd021SJiri Olsa int (*func)(struct evsel *evsel, 23814ba1faa1SWang Nan const void *arg), 23824ba1faa1SWang Nan const void *arg) 2383c171b552SLi Zefan { 238432dcd021SJiri Olsa struct evsel *last = NULL; 23854ba1faa1SWang Nan int err; 2386c171b552SLi Zefan 2387854f7363SWang Nan /* 2388854f7363SWang Nan * Don't return when list_empty, give func a chance to report 2389854f7363SWang Nan * error when it found last == NULL. 2390854f7363SWang Nan * 2391854f7363SWang Nan * So no need to WARN here, let *func do this. 2392854f7363SWang Nan */ 23936484d2f9SJiri Olsa if (evlist->core.nr_entries > 0) 2394515dbe48SJiri Olsa last = evlist__last(evlist); 239569aad6f1SArnaldo Carvalho de Melo 239615bfd2ccSWang Nan do { 23974ba1faa1SWang Nan err = (*func)(last, arg); 23984ba1faa1SWang Nan if (err) 2399c171b552SLi Zefan return -1; 24004ba1faa1SWang Nan if (!last) 24014ba1faa1SWang Nan return 0; 2402c171b552SLi Zefan 2403ce9036a6SJiri Olsa if (last->core.node.prev == &evlist->core.entries) 240415bfd2ccSWang Nan return 0; 2405b27c4eceSJiri Olsa last = list_entry(last->core.node.prev, struct evsel, core.node); 240615bfd2ccSWang Nan } while (!last->cmdline_group_boundary); 240715bfd2ccSWang Nan 2408c171b552SLi Zefan return 0; 2409c171b552SLi Zefan } 2410c171b552SLi Zefan 241132dcd021SJiri Olsa static int set_filter(struct evsel *evsel, const void *arg) 24124ba1faa1SWang Nan { 24134ba1faa1SWang Nan const char *str = arg; 24141e857484SMathieu Poirier bool found = false; 24151e857484SMathieu Poirier int nr_addr_filters = 0; 24161e857484SMathieu Poirier struct perf_pmu *pmu = NULL; 24174ba1faa1SWang Nan 241849836f78SJack Henschel if (evsel == NULL) { 241949836f78SJack Henschel fprintf(stderr, 242049836f78SJack Henschel "--filter option should follow a -e tracepoint or HW tracer option\n"); 242149836f78SJack Henschel return -1; 242249836f78SJack Henschel } 24234ba1faa1SWang Nan 24241fc632ceSJiri Olsa if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT) { 2425ad681adfSArnaldo Carvalho de Melo if (evsel__append_tp_filter(evsel, str) < 0) { 24264ba1faa1SWang Nan fprintf(stderr, 24274ba1faa1SWang Nan "not enough memory to hold filter string\n"); 24284ba1faa1SWang Nan return -1; 24294ba1faa1SWang Nan } 24304ba1faa1SWang Nan 24314ba1faa1SWang Nan return 0; 24324ba1faa1SWang Nan } 24334ba1faa1SWang Nan 24341eaf496eSIan Rogers while ((pmu = perf_pmus__scan(pmu)) != NULL) 24351fc632ceSJiri Olsa if (pmu->type == evsel->core.attr.type) { 24361e857484SMathieu Poirier found = true; 24371e857484SMathieu Poirier break; 24381e857484SMathieu Poirier } 24391e857484SMathieu Poirier 24401e857484SMathieu Poirier if (found) 24411e857484SMathieu Poirier perf_pmu__scan_file(pmu, "nr_addr_filters", 24421e857484SMathieu Poirier "%d", &nr_addr_filters); 24431e857484SMathieu Poirier 2444d180aa56SNamhyung Kim if (!nr_addr_filters) 2445d180aa56SNamhyung Kim return perf_bpf_filter__parse(&evsel->bpf_filters, str); 24461e857484SMathieu Poirier 2447ad681adfSArnaldo Carvalho de Melo if (evsel__append_addr_filter(evsel, str) < 0) { 24481e857484SMathieu Poirier fprintf(stderr, 24491e857484SMathieu Poirier "not enough memory to hold filter string\n"); 24501e857484SMathieu Poirier return -1; 24511e857484SMathieu Poirier } 24521e857484SMathieu Poirier 24531e857484SMathieu Poirier return 0; 24541e857484SMathieu Poirier } 24551e857484SMathieu Poirier 24564ba1faa1SWang Nan int parse_filter(const struct option *opt, const char *str, 24574ba1faa1SWang Nan int unset __maybe_unused) 24584ba1faa1SWang Nan { 245963503dbaSJiri Olsa struct evlist *evlist = *(struct evlist **)opt->value; 24604ba1faa1SWang Nan 24614ba1faa1SWang Nan return foreach_evsel_in_last_glob(evlist, set_filter, 24624ba1faa1SWang Nan (const void *)str); 24634ba1faa1SWang Nan } 24644ba1faa1SWang Nan 246532dcd021SJiri Olsa static int add_exclude_perf_filter(struct evsel *evsel, 24664ba1faa1SWang Nan const void *arg __maybe_unused) 24674ba1faa1SWang Nan { 24684ba1faa1SWang Nan char new_filter[64]; 24694ba1faa1SWang Nan 24701fc632ceSJiri Olsa if (evsel == NULL || evsel->core.attr.type != PERF_TYPE_TRACEPOINT) { 24714ba1faa1SWang Nan fprintf(stderr, 24724ba1faa1SWang Nan "--exclude-perf option should follow a -e tracepoint option\n"); 24734ba1faa1SWang Nan return -1; 24744ba1faa1SWang Nan } 24754ba1faa1SWang Nan 24764ba1faa1SWang Nan snprintf(new_filter, sizeof(new_filter), "common_pid != %d", getpid()); 24774ba1faa1SWang Nan 2478ad681adfSArnaldo Carvalho de Melo if (evsel__append_tp_filter(evsel, new_filter) < 0) { 24794ba1faa1SWang Nan fprintf(stderr, 24804ba1faa1SWang Nan "not enough memory to hold filter string\n"); 24814ba1faa1SWang Nan return -1; 24824ba1faa1SWang Nan } 24834ba1faa1SWang Nan 24844ba1faa1SWang Nan return 0; 24854ba1faa1SWang Nan } 24864ba1faa1SWang Nan 24874ba1faa1SWang Nan int exclude_perf(const struct option *opt, 24884ba1faa1SWang Nan const char *arg __maybe_unused, 24894ba1faa1SWang Nan int unset __maybe_unused) 24904ba1faa1SWang Nan { 249163503dbaSJiri Olsa struct evlist *evlist = *(struct evlist **)opt->value; 24924ba1faa1SWang Nan 24934ba1faa1SWang Nan return foreach_evsel_in_last_glob(evlist, add_exclude_perf_filter, 24944ba1faa1SWang Nan NULL); 24954ba1faa1SWang Nan } 24964ba1faa1SWang Nan 24976cee6cd3SArnaldo Carvalho de Melo int parse_events__is_hardcoded_term(struct parse_events_term *term) 24988f707d84SJiri Olsa { 249916fa7e82SJiri Olsa return term->type_term != PARSE_EVENTS__TERM_TYPE_USER; 25008f707d84SJiri Olsa } 25018f707d84SJiri Olsa 250267b49b38SJiri Olsa static int new_term(struct parse_events_term **_term, 250367b49b38SJiri Olsa struct parse_events_term *temp, 250467b49b38SJiri Olsa char *str, u64 num) 25058f707d84SJiri Olsa { 25066cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term; 25078f707d84SJiri Olsa 250867b49b38SJiri Olsa term = malloc(sizeof(*term)); 25098f707d84SJiri Olsa if (!term) 25108f707d84SJiri Olsa return -ENOMEM; 25118f707d84SJiri Olsa 251267b49b38SJiri Olsa *term = *temp; 25138f707d84SJiri Olsa INIT_LIST_HEAD(&term->list); 2514c2f1ceadSAndi Kleen term->weak = false; 25158f707d84SJiri Olsa 251667b49b38SJiri Olsa switch (term->type_val) { 25178f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_NUM: 25188f707d84SJiri Olsa term->val.num = num; 25198f707d84SJiri Olsa break; 25208f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_STR: 25218f707d84SJiri Olsa term->val.str = str; 25228f707d84SJiri Olsa break; 25238f707d84SJiri Olsa default: 25244be8be6bSAdrian Hunter free(term); 25258f707d84SJiri Olsa return -EINVAL; 25268f707d84SJiri Olsa } 25278f707d84SJiri Olsa 25288f707d84SJiri Olsa *_term = term; 25298f707d84SJiri Olsa return 0; 25308f707d84SJiri Olsa } 25318f707d84SJiri Olsa 25326cee6cd3SArnaldo Carvalho de Melo int parse_events_term__num(struct parse_events_term **term, 253358d3a4ceSIan Rogers enum parse_events__term_type type_term, 253458d3a4ceSIan Rogers const char *config, u64 num, 253599e7138eSJiri Olsa bool no_value, 2536bb78ce7dSAdrian Hunter void *loc_term_, void *loc_val_) 253716fa7e82SJiri Olsa { 2538bb78ce7dSAdrian Hunter YYLTYPE *loc_term = loc_term_; 2539bb78ce7dSAdrian Hunter YYLTYPE *loc_val = loc_val_; 2540bb78ce7dSAdrian Hunter 254167b49b38SJiri Olsa struct parse_events_term temp = { 254267b49b38SJiri Olsa .type_val = PARSE_EVENTS__TERM_TYPE_NUM, 254367b49b38SJiri Olsa .type_term = type_term, 254458d3a4ceSIan Rogers .config = config ? : strdup(config_term_name(type_term)), 254599e7138eSJiri Olsa .no_value = no_value, 254667b49b38SJiri Olsa .err_term = loc_term ? loc_term->first_column : 0, 254767b49b38SJiri Olsa .err_val = loc_val ? loc_val->first_column : 0, 254867b49b38SJiri Olsa }; 254967b49b38SJiri Olsa 255064199ae4SIan Rogers return new_term(term, &temp, /*str=*/NULL, num); 255116fa7e82SJiri Olsa } 255216fa7e82SJiri Olsa 25536cee6cd3SArnaldo Carvalho de Melo int parse_events_term__str(struct parse_events_term **term, 255458d3a4ceSIan Rogers enum parse_events__term_type type_term, 255558d3a4ceSIan Rogers char *config, char *str, 2556bb78ce7dSAdrian Hunter void *loc_term_, void *loc_val_) 255716fa7e82SJiri Olsa { 2558bb78ce7dSAdrian Hunter YYLTYPE *loc_term = loc_term_; 2559bb78ce7dSAdrian Hunter YYLTYPE *loc_val = loc_val_; 2560bb78ce7dSAdrian Hunter 256167b49b38SJiri Olsa struct parse_events_term temp = { 256267b49b38SJiri Olsa .type_val = PARSE_EVENTS__TERM_TYPE_STR, 256367b49b38SJiri Olsa .type_term = type_term, 256467b49b38SJiri Olsa .config = config, 256567b49b38SJiri Olsa .err_term = loc_term ? loc_term->first_column : 0, 256667b49b38SJiri Olsa .err_val = loc_val ? loc_val->first_column : 0, 256767b49b38SJiri Olsa }; 256867b49b38SJiri Olsa 256964199ae4SIan Rogers return new_term(term, &temp, str, /*num=*/0); 257016fa7e82SJiri Olsa } 257116fa7e82SJiri Olsa 2572e831f3ccSIan Rogers int parse_events_term__term(struct parse_events_term **term, 257358d3a4ceSIan Rogers enum parse_events__term_type term_lhs, 257458d3a4ceSIan Rogers enum parse_events__term_type term_rhs, 2575e831f3ccSIan Rogers void *loc_term, void *loc_val) 2576e831f3ccSIan Rogers { 2577e831f3ccSIan Rogers return parse_events_term__str(term, term_lhs, NULL, 257858d3a4ceSIan Rogers strdup(config_term_name(term_rhs)), 2579e831f3ccSIan Rogers loc_term, loc_val); 2580e831f3ccSIan Rogers } 2581e831f3ccSIan Rogers 25826cee6cd3SArnaldo Carvalho de Melo int parse_events_term__clone(struct parse_events_term **new, 2583aa1551f2SIan Rogers const struct parse_events_term *term) 2584a6146d50SZheng Yan { 2585b6645a72SIan Rogers char *str; 258664199ae4SIan Rogers struct parse_events_term temp = *term; 258767b49b38SJiri Olsa 258864199ae4SIan Rogers temp.used = false; 2589b6645a72SIan Rogers if (term->config) { 2590b6645a72SIan Rogers temp.config = strdup(term->config); 2591b6645a72SIan Rogers if (!temp.config) 2592b6645a72SIan Rogers return -ENOMEM; 2593b6645a72SIan Rogers } 2594b6645a72SIan Rogers if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) 259564199ae4SIan Rogers return new_term(new, &temp, /*str=*/NULL, term->val.num); 2596b6645a72SIan Rogers 2597b6645a72SIan Rogers str = strdup(term->val.str); 25987875c72cSIan Rogers if (!str) { 25997875c72cSIan Rogers zfree(&temp.config); 2600b6645a72SIan Rogers return -ENOMEM; 26017875c72cSIan Rogers } 260264199ae4SIan Rogers return new_term(new, &temp, str, /*num=*/0); 2603a6146d50SZheng Yan } 2604a6146d50SZheng Yan 26051dc92556SIan Rogers void parse_events_term__delete(struct parse_events_term *term) 26061dc92556SIan Rogers { 26071dc92556SIan Rogers if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM) 26081dc92556SIan Rogers zfree(&term->val.str); 26091dc92556SIan Rogers 26101dc92556SIan Rogers zfree(&term->config); 26111dc92556SIan Rogers free(term); 26121dc92556SIan Rogers } 26131dc92556SIan Rogers 26140d3f0e6fSIan Rogers static int parse_events_terms__copy(const struct parse_events_terms *src, 26150d3f0e6fSIan Rogers struct parse_events_terms *dest) 26168255718fSAndi Kleen { 2617727adeedSIan Rogers struct parse_events_term *term; 2618727adeedSIan Rogers 26190d3f0e6fSIan Rogers list_for_each_entry (term, &src->terms, list) { 2620727adeedSIan Rogers struct parse_events_term *n; 26218255718fSAndi Kleen int ret; 26228255718fSAndi Kleen 26238255718fSAndi Kleen ret = parse_events_term__clone(&n, term); 26248255718fSAndi Kleen if (ret) 26258255718fSAndi Kleen return ret; 2626727adeedSIan Rogers 26270d3f0e6fSIan Rogers list_add_tail(&n->list, &dest->terms); 26288255718fSAndi Kleen } 26298255718fSAndi Kleen return 0; 26308255718fSAndi Kleen } 26318255718fSAndi Kleen 26320d3f0e6fSIan Rogers void parse_events_terms__init(struct parse_events_terms *terms) 26330d3f0e6fSIan Rogers { 26340d3f0e6fSIan Rogers INIT_LIST_HEAD(&terms->terms); 26350d3f0e6fSIan Rogers } 26360d3f0e6fSIan Rogers 26370d3f0e6fSIan Rogers void parse_events_terms__exit(struct parse_events_terms *terms) 26388f707d84SJiri Olsa { 26396cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term, *h; 26408f707d84SJiri Olsa 26410d3f0e6fSIan Rogers list_for_each_entry_safe(term, h, &terms->terms, list) { 2642a8adfcebSWang Nan list_del_init(&term->list); 26431dc92556SIan Rogers parse_events_term__delete(term); 26448f707d84SJiri Olsa } 2645a8adfcebSWang Nan } 2646b39b8393SJiri Olsa 26470d3f0e6fSIan Rogers void parse_events_terms__delete(struct parse_events_terms *terms) 2648fc0a2c1dSArnaldo Carvalho de Melo { 26492146afc6SArnaldo Carvalho de Melo if (!terms) 26502146afc6SArnaldo Carvalho de Melo return; 26510d3f0e6fSIan Rogers parse_events_terms__exit(terms); 2652d20a5f2bSWang Nan free(terms); 2653fc0a2c1dSArnaldo Carvalho de Melo } 2654fc0a2c1dSArnaldo Carvalho de Melo 26550d3f0e6fSIan Rogers int parse_events_terms__to_strbuf(const struct parse_events_terms *terms, struct strbuf *sb) 26567a6e9164SIan Rogers { 26577a6e9164SIan Rogers struct parse_events_term *term; 26587a6e9164SIan Rogers bool first = true; 26597a6e9164SIan Rogers 26600d3f0e6fSIan Rogers if (!terms) 26617a6e9164SIan Rogers return 0; 26627a6e9164SIan Rogers 26630d3f0e6fSIan Rogers list_for_each_entry(term, &terms->terms, list) { 26647a6e9164SIan Rogers int ret; 26657a6e9164SIan Rogers 26667a6e9164SIan Rogers if (!first) { 26677a6e9164SIan Rogers ret = strbuf_addch(sb, ','); 26687a6e9164SIan Rogers if (ret < 0) 26697a6e9164SIan Rogers return ret; 26707a6e9164SIan Rogers } 26717a6e9164SIan Rogers first = false; 26727a6e9164SIan Rogers 26737a6e9164SIan Rogers if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) 267464199ae4SIan Rogers if (term->no_value) { 26759ea150a8SIan Rogers assert(term->val.num == 1); 26767a6e9164SIan Rogers ret = strbuf_addf(sb, "%s", term->config); 267764199ae4SIan Rogers } else 26787a6e9164SIan Rogers ret = strbuf_addf(sb, "%s=%#"PRIx64, term->config, term->val.num); 26797a6e9164SIan Rogers else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) { 26807a6e9164SIan Rogers if (term->config) { 26817a6e9164SIan Rogers ret = strbuf_addf(sb, "%s=", term->config); 26827a6e9164SIan Rogers if (ret < 0) 26837a6e9164SIan Rogers return ret; 268464199ae4SIan Rogers } else if ((unsigned int)term->type_term < __PARSE_EVENTS__TERM_TYPE_NR) { 268558d3a4ceSIan Rogers ret = strbuf_addf(sb, "%s=", config_term_name(term->type_term)); 26867a6e9164SIan Rogers if (ret < 0) 26877a6e9164SIan Rogers return ret; 26887a6e9164SIan Rogers } 268964199ae4SIan Rogers assert(!term->no_value); 26907a6e9164SIan Rogers ret = strbuf_addf(sb, "%s", term->val.str); 26917a6e9164SIan Rogers } 26927a6e9164SIan Rogers if (ret < 0) 26937a6e9164SIan Rogers return ret; 26947a6e9164SIan Rogers } 26957a6e9164SIan Rogers return 0; 26967a6e9164SIan Rogers } 26977a6e9164SIan Rogers 269817cb5f84SWang Nan static void config_terms_list(char *buf, size_t buf_sz) 269917cb5f84SWang Nan { 270017cb5f84SWang Nan int i; 270117cb5f84SWang Nan bool first = true; 270217cb5f84SWang Nan 270317cb5f84SWang Nan buf[0] = '\0'; 270417cb5f84SWang Nan for (i = 0; i < __PARSE_EVENTS__TERM_TYPE_NR; i++) { 270558d3a4ceSIan Rogers const char *name = config_term_name(i); 270617cb5f84SWang Nan 27071669e509SWang Nan if (!config_term_avail(i, NULL)) 27081669e509SWang Nan continue; 270917cb5f84SWang Nan if (!name) 271017cb5f84SWang Nan continue; 271117cb5f84SWang Nan if (name[0] == '<') 271217cb5f84SWang Nan continue; 271317cb5f84SWang Nan 271417cb5f84SWang Nan if (strlen(buf) + strlen(name) + 2 >= buf_sz) 271517cb5f84SWang Nan return; 271617cb5f84SWang Nan 271717cb5f84SWang Nan if (!first) 271817cb5f84SWang Nan strcat(buf, ","); 271917cb5f84SWang Nan else 272017cb5f84SWang Nan first = false; 272117cb5f84SWang Nan strcat(buf, name); 272217cb5f84SWang Nan } 272317cb5f84SWang Nan } 272417cb5f84SWang Nan 2725ffeb883eSHe Kuang /* 2726ffeb883eSHe Kuang * Return string contains valid config terms of an event. 2727ffeb883eSHe Kuang * @additional_terms: For terms such as PMU sysfs terms. 2728ffeb883eSHe Kuang */ 2729ffeb883eSHe Kuang char *parse_events_formats_error_string(char *additional_terms) 2730ffeb883eSHe Kuang { 2731ffeb883eSHe Kuang char *str; 2732626a6b78SWang Nan /* "no-overwrite" is the longest name */ 273317cb5f84SWang Nan char static_terms[__PARSE_EVENTS__TERM_TYPE_NR * 2734626a6b78SWang Nan (sizeof("no-overwrite") - 1)]; 2735ffeb883eSHe Kuang 273617cb5f84SWang Nan config_terms_list(static_terms, sizeof(static_terms)); 2737ffeb883eSHe Kuang /* valid terms */ 2738ffeb883eSHe Kuang if (additional_terms) { 273926dee028SWang Nan if (asprintf(&str, "valid terms: %s,%s", 274026dee028SWang Nan additional_terms, static_terms) < 0) 2741ffeb883eSHe Kuang goto fail; 2742ffeb883eSHe Kuang } else { 274326dee028SWang Nan if (asprintf(&str, "valid terms: %s", static_terms) < 0) 2744ffeb883eSHe Kuang goto fail; 2745ffeb883eSHe Kuang } 2746ffeb883eSHe Kuang return str; 2747ffeb883eSHe Kuang 2748ffeb883eSHe Kuang fail: 2749ffeb883eSHe Kuang return NULL; 2750ffeb883eSHe Kuang } 2751