xref: /linux/tools/perf/util/parse-events.c (revision e831f3ccf9920fa099d4ebb9d57214cc7ecd2e70)
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"
168ec20b17SArnaldo Carvalho de Melo #include "strlist.h"
1784c86ca1SWang Nan #include "bpf-loader.h"
186e81c74cSMasami Hiramatsu #include "debug.h"
19592d5a6bSJiri Olsa #include <api/fs/tracing_path.h>
209c3516d1SJiri Olsa #include <perf/cpumap.h>
21ac20de6fSZheng Yan #include "parse-events-bison.h"
2289812fc8SJiri Olsa #include "parse-events-flex.h"
235f537a26SJiri Olsa #include "pmu.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"
3171c86cdaSZhengjun Xing #include "thread_map.h"
3289812fc8SJiri Olsa 
3389812fc8SJiri Olsa #define MAX_NAME_LEN 100
3486470930SIngo Molnar 
3582ba1f2fSJiri Olsa #ifdef PARSER_DEBUG
3682ba1f2fSJiri Olsa extern int parse_events_debug;
3782ba1f2fSJiri Olsa #endif
385d9cdc11SArnaldo Carvalho de Melo int parse_events_parse(void *parse_state, void *scanner);
39e637d177SHe Kuang static int get_config_terms(struct list_head *head_config,
40e637d177SHe Kuang 			    struct list_head *head_terms __maybe_unused);
41bcd3279fSFrederic Weisbecker 
42705750f2SYunlong Song struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = {
431dc12760SJiri Olsa 	[PERF_COUNT_HW_CPU_CYCLES] = {
441dc12760SJiri Olsa 		.symbol = "cpu-cycles",
451dc12760SJiri Olsa 		.alias  = "cycles",
461dc12760SJiri Olsa 	},
471dc12760SJiri Olsa 	[PERF_COUNT_HW_INSTRUCTIONS] = {
481dc12760SJiri Olsa 		.symbol = "instructions",
491dc12760SJiri Olsa 		.alias  = "",
501dc12760SJiri Olsa 	},
511dc12760SJiri Olsa 	[PERF_COUNT_HW_CACHE_REFERENCES] = {
521dc12760SJiri Olsa 		.symbol = "cache-references",
531dc12760SJiri Olsa 		.alias  = "",
541dc12760SJiri Olsa 	},
551dc12760SJiri Olsa 	[PERF_COUNT_HW_CACHE_MISSES] = {
561dc12760SJiri Olsa 		.symbol = "cache-misses",
571dc12760SJiri Olsa 		.alias  = "",
581dc12760SJiri Olsa 	},
591dc12760SJiri Olsa 	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = {
601dc12760SJiri Olsa 		.symbol = "branch-instructions",
611dc12760SJiri Olsa 		.alias  = "branches",
621dc12760SJiri Olsa 	},
631dc12760SJiri Olsa 	[PERF_COUNT_HW_BRANCH_MISSES] = {
641dc12760SJiri Olsa 		.symbol = "branch-misses",
651dc12760SJiri Olsa 		.alias  = "",
661dc12760SJiri Olsa 	},
671dc12760SJiri Olsa 	[PERF_COUNT_HW_BUS_CYCLES] = {
681dc12760SJiri Olsa 		.symbol = "bus-cycles",
691dc12760SJiri Olsa 		.alias  = "",
701dc12760SJiri Olsa 	},
711dc12760SJiri Olsa 	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = {
721dc12760SJiri Olsa 		.symbol = "stalled-cycles-frontend",
731dc12760SJiri Olsa 		.alias  = "idle-cycles-frontend",
741dc12760SJiri Olsa 	},
751dc12760SJiri Olsa 	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = {
761dc12760SJiri Olsa 		.symbol = "stalled-cycles-backend",
771dc12760SJiri Olsa 		.alias  = "idle-cycles-backend",
781dc12760SJiri Olsa 	},
791dc12760SJiri Olsa 	[PERF_COUNT_HW_REF_CPU_CYCLES] = {
801dc12760SJiri Olsa 		.symbol = "ref-cycles",
811dc12760SJiri Olsa 		.alias  = "",
821dc12760SJiri Olsa 	},
831dc12760SJiri Olsa };
8486470930SIngo Molnar 
85705750f2SYunlong Song struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
861dc12760SJiri Olsa 	[PERF_COUNT_SW_CPU_CLOCK] = {
871dc12760SJiri Olsa 		.symbol = "cpu-clock",
881dc12760SJiri Olsa 		.alias  = "",
891dc12760SJiri Olsa 	},
901dc12760SJiri Olsa 	[PERF_COUNT_SW_TASK_CLOCK] = {
911dc12760SJiri Olsa 		.symbol = "task-clock",
921dc12760SJiri Olsa 		.alias  = "",
931dc12760SJiri Olsa 	},
941dc12760SJiri Olsa 	[PERF_COUNT_SW_PAGE_FAULTS] = {
951dc12760SJiri Olsa 		.symbol = "page-faults",
961dc12760SJiri Olsa 		.alias  = "faults",
971dc12760SJiri Olsa 	},
981dc12760SJiri Olsa 	[PERF_COUNT_SW_CONTEXT_SWITCHES] = {
991dc12760SJiri Olsa 		.symbol = "context-switches",
1001dc12760SJiri Olsa 		.alias  = "cs",
1011dc12760SJiri Olsa 	},
1021dc12760SJiri Olsa 	[PERF_COUNT_SW_CPU_MIGRATIONS] = {
1031dc12760SJiri Olsa 		.symbol = "cpu-migrations",
1041dc12760SJiri Olsa 		.alias  = "migrations",
1051dc12760SJiri Olsa 	},
1061dc12760SJiri Olsa 	[PERF_COUNT_SW_PAGE_FAULTS_MIN] = {
1071dc12760SJiri Olsa 		.symbol = "minor-faults",
1081dc12760SJiri Olsa 		.alias  = "",
1091dc12760SJiri Olsa 	},
1101dc12760SJiri Olsa 	[PERF_COUNT_SW_PAGE_FAULTS_MAJ] = {
1111dc12760SJiri Olsa 		.symbol = "major-faults",
1121dc12760SJiri Olsa 		.alias  = "",
1131dc12760SJiri Olsa 	},
1141dc12760SJiri Olsa 	[PERF_COUNT_SW_ALIGNMENT_FAULTS] = {
1151dc12760SJiri Olsa 		.symbol = "alignment-faults",
1161dc12760SJiri Olsa 		.alias  = "",
1171dc12760SJiri Olsa 	},
1181dc12760SJiri Olsa 	[PERF_COUNT_SW_EMULATION_FAULTS] = {
1191dc12760SJiri Olsa 		.symbol = "emulation-faults",
1201dc12760SJiri Olsa 		.alias  = "",
1211dc12760SJiri Olsa 	},
122d22d1a2aSAdrian Hunter 	[PERF_COUNT_SW_DUMMY] = {
123d22d1a2aSAdrian Hunter 		.symbol = "dummy",
124d22d1a2aSAdrian Hunter 		.alias  = "",
125d22d1a2aSAdrian Hunter 	},
126bae9cc41SArnaldo Carvalho de Melo 	[PERF_COUNT_SW_BPF_OUTPUT] = {
127bae9cc41SArnaldo Carvalho de Melo 		.symbol = "bpf-output",
128bae9cc41SArnaldo Carvalho de Melo 		.alias  = "",
129bae9cc41SArnaldo Carvalho de Melo 	},
130fb6c79d7SNamhyung Kim 	[PERF_COUNT_SW_CGROUP_SWITCHES] = {
131fb6c79d7SNamhyung Kim 		.symbol = "cgroup-switches",
132fb6c79d7SNamhyung Kim 		.alias  = "",
133fb6c79d7SNamhyung Kim 	},
13486470930SIngo Molnar };
13586470930SIngo Molnar 
13671c86cdaSZhengjun Xing bool is_event_supported(u8 type, u64 config)
13771c86cdaSZhengjun Xing {
13871c86cdaSZhengjun Xing 	bool ret = true;
13971c86cdaSZhengjun Xing 	int open_return;
14071c86cdaSZhengjun Xing 	struct evsel *evsel;
14171c86cdaSZhengjun Xing 	struct perf_event_attr attr = {
14271c86cdaSZhengjun Xing 		.type = type,
14371c86cdaSZhengjun Xing 		.config = config,
14471c86cdaSZhengjun Xing 		.disabled = 1,
14571c86cdaSZhengjun Xing 	};
14671c86cdaSZhengjun Xing 	struct perf_thread_map *tmap = thread_map__new_by_tid(0);
14771c86cdaSZhengjun Xing 
14871c86cdaSZhengjun Xing 	if (tmap == NULL)
14971c86cdaSZhengjun Xing 		return false;
15071c86cdaSZhengjun Xing 
15171c86cdaSZhengjun Xing 	evsel = evsel__new(&attr);
15271c86cdaSZhengjun Xing 	if (evsel) {
15371c86cdaSZhengjun Xing 		open_return = evsel__open(evsel, NULL, tmap);
15471c86cdaSZhengjun Xing 		ret = open_return >= 0;
15571c86cdaSZhengjun Xing 
15671c86cdaSZhengjun Xing 		if (open_return == -EACCES) {
15771c86cdaSZhengjun Xing 			/*
15871c86cdaSZhengjun Xing 			 * This happens if the paranoid value
15971c86cdaSZhengjun Xing 			 * /proc/sys/kernel/perf_event_paranoid is set to 2
16071c86cdaSZhengjun Xing 			 * Re-run with exclude_kernel set; we don't do that
16171c86cdaSZhengjun Xing 			 * by default as some ARM machines do not support it.
16271c86cdaSZhengjun Xing 			 *
16371c86cdaSZhengjun Xing 			 */
16471c86cdaSZhengjun Xing 			evsel->core.attr.exclude_kernel = 1;
16571c86cdaSZhengjun Xing 			ret = evsel__open(evsel, NULL, tmap) >= 0;
16671c86cdaSZhengjun Xing 		}
16771c86cdaSZhengjun Xing 		evsel__delete(evsel);
16871c86cdaSZhengjun Xing 	}
16971c86cdaSZhengjun Xing 
17071c86cdaSZhengjun Xing 	perf_thread_map__put(tmap);
17171c86cdaSZhengjun Xing 	return ret;
17271c86cdaSZhengjun Xing }
17371c86cdaSZhengjun Xing 
1741424dc96SDavid Ahern const char *event_type(int type)
1751424dc96SDavid Ahern {
1761424dc96SDavid Ahern 	switch (type) {
1771424dc96SDavid Ahern 	case PERF_TYPE_HARDWARE:
1781424dc96SDavid Ahern 		return "hardware";
1791424dc96SDavid Ahern 
1801424dc96SDavid Ahern 	case PERF_TYPE_SOFTWARE:
1811424dc96SDavid Ahern 		return "software";
1821424dc96SDavid Ahern 
1831424dc96SDavid Ahern 	case PERF_TYPE_TRACEPOINT:
1841424dc96SDavid Ahern 		return "tracepoint";
1851424dc96SDavid Ahern 
1861424dc96SDavid Ahern 	case PERF_TYPE_HW_CACHE:
1871424dc96SDavid Ahern 		return "hardware-cache";
1881424dc96SDavid Ahern 
1891424dc96SDavid Ahern 	default:
1901424dc96SDavid Ahern 		break;
1911424dc96SDavid Ahern 	}
1921424dc96SDavid Ahern 
1931424dc96SDavid Ahern 	return "unknown";
1941424dc96SDavid Ahern }
1951424dc96SDavid Ahern 
1962b62b3a6SIan Rogers static char *get_config_str(struct list_head *head_terms, int type_term)
197e814fdddSWang Nan {
198e814fdddSWang Nan 	struct parse_events_term *term;
199e814fdddSWang Nan 
200e814fdddSWang Nan 	if (!head_terms)
201e814fdddSWang Nan 		return NULL;
202e814fdddSWang Nan 
203e814fdddSWang Nan 	list_for_each_entry(term, head_terms, list)
2042b62b3a6SIan Rogers 		if (term->type_term == type_term)
205e814fdddSWang Nan 			return term->val.str;
206e814fdddSWang Nan 
207e814fdddSWang Nan 	return NULL;
208e814fdddSWang Nan }
2097ae92e74SYan, Zheng 
2102b62b3a6SIan Rogers static char *get_config_metric_id(struct list_head *head_terms)
2112b62b3a6SIan Rogers {
2122b62b3a6SIan Rogers 	return get_config_str(head_terms, PARSE_EVENTS__TERM_TYPE_METRIC_ID);
2132b62b3a6SIan Rogers }
2142b62b3a6SIan Rogers 
2152b62b3a6SIan Rogers static char *get_config_name(struct list_head *head_terms)
2162b62b3a6SIan Rogers {
2172b62b3a6SIan Rogers 	return get_config_str(head_terms, PARSE_EVENTS__TERM_TYPE_NAME);
2182b62b3a6SIan Rogers }
2192b62b3a6SIan Rogers 
22070c90e4aSIan Rogers /**
22170c90e4aSIan Rogers  * fix_raw - For each raw term see if there is an event (aka alias) in pmu that
22270c90e4aSIan Rogers  *           matches the raw's string value. If the string value matches an
22370c90e4aSIan Rogers  *           event then change the term to be an event, if not then change it to
22470c90e4aSIan Rogers  *           be a config term. For example, "read" may be an event of the PMU or
22570c90e4aSIan Rogers  *           a raw hex encoding of 0xead. The fix-up is done late so the PMU of
22670c90e4aSIan Rogers  *           the event can be determined and we don't need to scan all PMUs
22770c90e4aSIan Rogers  *           ahead-of-time.
22870c90e4aSIan Rogers  * @config_terms: the list of terms that may contain a raw term.
22970c90e4aSIan Rogers  * @pmu: the PMU to scan for events from.
23070c90e4aSIan Rogers  */
23170c90e4aSIan Rogers static void fix_raw(struct list_head *config_terms, struct perf_pmu *pmu)
23270c90e4aSIan Rogers {
23370c90e4aSIan Rogers 	struct parse_events_term *term;
23470c90e4aSIan Rogers 
23570c90e4aSIan Rogers 	list_for_each_entry(term, config_terms, list) {
23670c90e4aSIan Rogers 		struct perf_pmu_alias *alias;
23770c90e4aSIan Rogers 		bool matched = false;
23870c90e4aSIan Rogers 
23970c90e4aSIan Rogers 		if (term->type_term != PARSE_EVENTS__TERM_TYPE_RAW)
24070c90e4aSIan Rogers 			continue;
24170c90e4aSIan Rogers 
24270c90e4aSIan Rogers 		list_for_each_entry(alias, &pmu->aliases, list) {
24370c90e4aSIan Rogers 			if (!strcmp(alias->name, term->val.str)) {
24470c90e4aSIan Rogers 				free(term->config);
24570c90e4aSIan Rogers 				term->config = term->val.str;
24670c90e4aSIan Rogers 				term->type_val = PARSE_EVENTS__TERM_TYPE_NUM;
24770c90e4aSIan Rogers 				term->type_term = PARSE_EVENTS__TERM_TYPE_USER;
24870c90e4aSIan Rogers 				term->val.num = 1;
24970c90e4aSIan Rogers 				term->no_value = true;
25070c90e4aSIan Rogers 				matched = true;
25170c90e4aSIan Rogers 				break;
25270c90e4aSIan Rogers 			}
25370c90e4aSIan Rogers 		}
25470c90e4aSIan Rogers 		if (!matched) {
25570c90e4aSIan Rogers 			u64 num;
25670c90e4aSIan Rogers 
25770c90e4aSIan Rogers 			free(term->config);
25870c90e4aSIan Rogers 			term->config = strdup("config");
25970c90e4aSIan Rogers 			errno = 0;
26070c90e4aSIan Rogers 			num = strtoull(term->val.str + 1, NULL, 16);
26170c90e4aSIan Rogers 			assert(errno == 0);
26270c90e4aSIan Rogers 			free(term->val.str);
26370c90e4aSIan Rogers 			term->type_val = PARSE_EVENTS__TERM_TYPE_NUM;
26470c90e4aSIan Rogers 			term->type_term = PARSE_EVENTS__TERM_TYPE_CONFIG;
26570c90e4aSIan Rogers 			term->val.num = num;
26670c90e4aSIan Rogers 			term->no_value = false;
26770c90e4aSIan Rogers 		}
26870c90e4aSIan Rogers 	}
26970c90e4aSIan Rogers }
27070c90e4aSIan Rogers 
27132dcd021SJiri Olsa static struct evsel *
272410136f5SStephane Eranian __add_event(struct list_head *list, int *idx,
2737ae92e74SYan, Zheng 	    struct perf_event_attr *attr,
27470943490SStephane Eranian 	    bool init_attr,
2752b62b3a6SIan Rogers 	    const char *name, const char *metric_id, struct perf_pmu *pmu,
276f0fbb114SAndi Kleen 	    struct list_head *config_terms, bool auto_merge_stats,
277f0fbb114SAndi Kleen 	    const char *cpu_list)
27889812fc8SJiri Olsa {
27932dcd021SJiri Olsa 	struct evsel *evsel;
2805d680be3SNamhyung Kim 	struct perf_cpu_map *cpus = pmu ? perf_cpu_map__get(pmu->cpus) :
2819c3516d1SJiri Olsa 			       cpu_list ? perf_cpu_map__new(cpu_list) : NULL;
28289812fc8SJiri Olsa 
283e552b7beSRob Herring 	if (pmu)
284e552b7beSRob Herring 		perf_pmu__warn_invalid_formats(pmu);
285e552b7beSRob Herring 
286e4064776SJin Yao 	if (pmu && attr->type == PERF_TYPE_RAW)
287e4064776SJin Yao 		perf_pmu__warn_invalid_config(pmu, attr->config, name);
288e4064776SJin Yao 
28970943490SStephane Eranian 	if (init_attr)
29089812fc8SJiri Olsa 		event_attr_init(attr);
29189812fc8SJiri Olsa 
2928f6725a2SArnaldo Carvalho de Melo 	evsel = evsel__new_idx(attr, *idx);
2930f1b550eSNamhyung Kim 	if (!evsel) {
2940f1b550eSNamhyung Kim 		perf_cpu_map__put(cpus);
295410136f5SStephane Eranian 		return NULL;
2960f1b550eSNamhyung Kim 	}
29789812fc8SJiri Olsa 
29875fc5ae5STaeung Song 	(*idx)++;
2995d680be3SNamhyung Kim 	evsel->core.cpus = cpus;
300fe1f61b3SJiri Olsa 	evsel->core.own_cpus = perf_cpu_map__get(cpus);
301d3345fecSAdrian Hunter 	evsel->core.requires_cpu = pmu ? pmu->is_uncore : false;
30263ce8449SArnaldo Carvalho de Melo 	evsel->auto_merge_stats = auto_merge_stats;
303f7400262SNamhyung Kim 	evsel->pmu = pmu;
304cae256aeSIan Rogers 	evsel->pmu_name = pmu && pmu->name ? strdup(pmu->name) : NULL;
305f30a79b0SJiri Olsa 
3069db1763cSArnaldo Carvalho de Melo 	if (name)
30789812fc8SJiri Olsa 		evsel->name = strdup(name);
308930a2e29SJiri Olsa 
3092b62b3a6SIan Rogers 	if (metric_id)
3102b62b3a6SIan Rogers 		evsel->metric_id = strdup(metric_id);
3112b62b3a6SIan Rogers 
312930a2e29SJiri Olsa 	if (config_terms)
31399fc5941SAdrian Hunter 		list_splice_init(config_terms, &evsel->config_terms);
314930a2e29SJiri Olsa 
31570943490SStephane Eranian 	if (list)
316b27c4eceSJiri Olsa 		list_add_tail(&evsel->core.node, list);
31770943490SStephane Eranian 
318410136f5SStephane Eranian 	return evsel;
31989812fc8SJiri Olsa }
32089812fc8SJiri Olsa 
32170943490SStephane Eranian struct evsel *parse_events__add_event(int idx, struct perf_event_attr *attr,
3222b62b3a6SIan Rogers 				      const char *name, const char *metric_id,
3232b62b3a6SIan Rogers 				      struct perf_pmu *pmu)
32470943490SStephane Eranian {
3252b62b3a6SIan Rogers 	return __add_event(/*list=*/NULL, &idx, attr, /*init_attr=*/false, name,
3262b62b3a6SIan Rogers 			   metric_id, pmu, /*config_terms=*/NULL,
3272b62b3a6SIan Rogers 			   /*auto_merge_stats=*/false, /*cpu_list=*/NULL);
32870943490SStephane Eranian }
32970943490SStephane Eranian 
330c5cd8ac0SDavid Ahern static int add_event(struct list_head *list, int *idx,
3318e8bbfb3SIan Rogers 		     struct perf_event_attr *attr, const char *name,
3322b62b3a6SIan Rogers 		     const char *metric_id, struct list_head *config_terms)
3337ae92e74SYan, Zheng {
3342b62b3a6SIan Rogers 	return __add_event(list, idx, attr, /*init_attr*/true, name, metric_id,
3352b62b3a6SIan Rogers 			   /*pmu=*/NULL, config_terms,
3362b62b3a6SIan Rogers 			   /*auto_merge_stats=*/false, /*cpu_list=*/NULL) ? 0 : -ENOMEM;
337f0fbb114SAndi Kleen }
338f0fbb114SAndi Kleen 
339f0fbb114SAndi Kleen static int add_event_tool(struct list_head *list, int *idx,
340f0fbb114SAndi Kleen 			  enum perf_tool_event tool_event)
341f0fbb114SAndi Kleen {
34232dcd021SJiri Olsa 	struct evsel *evsel;
343f0fbb114SAndi Kleen 	struct perf_event_attr attr = {
344f0fbb114SAndi Kleen 		.type = PERF_TYPE_SOFTWARE,
345f0fbb114SAndi Kleen 		.config = PERF_COUNT_SW_DUMMY,
346f0fbb114SAndi Kleen 	};
347f0fbb114SAndi Kleen 
3482b62b3a6SIan Rogers 	evsel = __add_event(list, idx, &attr, /*init_attr=*/true, /*name=*/NULL,
3492b62b3a6SIan Rogers 			    /*metric_id=*/NULL, /*pmu=*/NULL,
3502b62b3a6SIan Rogers 			    /*config_terms=*/NULL, /*auto_merge_stats=*/false,
3512b62b3a6SIan Rogers 			    /*cpu_list=*/"0");
352f0fbb114SAndi Kleen 	if (!evsel)
353f0fbb114SAndi Kleen 		return -ENOMEM;
354f0fbb114SAndi Kleen 	evsel->tool_event = tool_event;
355b03b89b3SFlorian Fischer 	if (tool_event == PERF_TOOL_DURATION_TIME
356b03b89b3SFlorian Fischer 	    || tool_event == PERF_TOOL_USER_TIME
357b03b89b3SFlorian Fischer 	    || tool_event == PERF_TOOL_SYSTEM_TIME) {
358b194c9cdSIan Rogers 		free((char *)evsel->unit);
359b194c9cdSIan Rogers 		evsel->unit = strdup("ns");
360b194c9cdSIan Rogers 	}
361f0fbb114SAndi Kleen 	return 0;
3627ae92e74SYan, Zheng }
3637ae92e74SYan, Zheng 
36470c90e4aSIan Rogers /**
36570c90e4aSIan Rogers  * parse_aliases - search names for entries beginning or equalling str ignoring
36670c90e4aSIan Rogers  *                 case. If mutliple entries in names match str then the longest
36770c90e4aSIan Rogers  *                 is chosen.
36870c90e4aSIan Rogers  * @str: The needle to look for.
36970c90e4aSIan Rogers  * @names: The haystack to search.
37070c90e4aSIan Rogers  * @size: The size of the haystack.
37170c90e4aSIan Rogers  * @longest: Out argument giving the length of the matching entry.
37270c90e4aSIan Rogers  */
37370c90e4aSIan Rogers static int parse_aliases(const char *str, const char *const names[][EVSEL__MAX_ALIASES], int size,
37470c90e4aSIan Rogers 			 int *longest)
37586470930SIngo Molnar {
37670c90e4aSIan Rogers 	*longest = -1;
37770c90e4aSIan Rogers 	for (int i = 0; i < size; i++) {
37870c90e4aSIan Rogers 		for (int j = 0; j < EVSEL__MAX_ALIASES && names[i][j]; j++) {
37970c90e4aSIan Rogers 			int n = strlen(names[i][j]);
38086470930SIngo Molnar 
38170c90e4aSIan Rogers 			if (n > *longest && !strncasecmp(str, names[i][j], n))
38270c90e4aSIan Rogers 				*longest = n;
38361c45981SPaul Mackerras 		}
38470c90e4aSIan Rogers 		if (*longest > 0)
38586470930SIngo Molnar 			return i;
38686470930SIngo Molnar 	}
38786470930SIngo Molnar 
3888953645fSIngo Molnar 	return -1;
38986470930SIngo Molnar }
39086470930SIngo Molnar 
39143d0b978SWang Nan typedef int config_term_func_t(struct perf_event_attr *attr,
39243d0b978SWang Nan 			       struct parse_events_term *term,
39343d0b978SWang Nan 			       struct parse_events_error *err);
39443d0b978SWang Nan static int config_term_common(struct perf_event_attr *attr,
39543d0b978SWang Nan 			      struct parse_events_term *term,
39643d0b978SWang Nan 			      struct parse_events_error *err);
39743d0b978SWang Nan static int config_attr(struct perf_event_attr *attr,
39843d0b978SWang Nan 		       struct list_head *head,
39943d0b978SWang Nan 		       struct parse_events_error *err,
40043d0b978SWang Nan 		       config_term_func_t config_term);
40143d0b978SWang Nan 
4026fd1e519SIan Rogers /**
4036fd1e519SIan Rogers  * parse_events__decode_legacy_cache - Search name for the legacy cache event
4046fd1e519SIan Rogers  *                                     name composed of 1, 2 or 3 hyphen
4056fd1e519SIan Rogers  *                                     separated sections. The first section is
4066fd1e519SIan Rogers  *                                     the cache type while the others are the
4076fd1e519SIan Rogers  *                                     optional op and optional result. To make
4086fd1e519SIan Rogers  *                                     life hard the names in the table also
4096fd1e519SIan Rogers  *                                     contain hyphens and the longest name
41070c90e4aSIan Rogers  *                                     should always be selected.
41186470930SIngo Molnar  */
412d7f21df0SIan Rogers int parse_events__decode_legacy_cache(const char *name, int pmu_type, __u64 *config)
4136fd1e519SIan Rogers {
4146fd1e519SIan Rogers 	int len, cache_type = -1, cache_op = -1, cache_result = -1;
4156fd1e519SIan Rogers 	const char *name_end = &name[strlen(name) + 1];
4166fd1e519SIan Rogers 	const char *str = name;
4176fd1e519SIan Rogers 
41870c90e4aSIan Rogers 	cache_type = parse_aliases(str, evsel__hw_cache, PERF_COUNT_HW_CACHE_MAX, &len);
41986470930SIngo Molnar 	if (cache_type == -1)
42089812fc8SJiri Olsa 		return -EINVAL;
42170c90e4aSIan Rogers 	str += len + 1;
42286470930SIngo Molnar 
42370c90e4aSIan Rogers 	if (str < name_end) {
424c64e85e1SArnaldo Carvalho de Melo 		cache_op = parse_aliases(str, evsel__hw_cache_op,
42570c90e4aSIan Rogers 					PERF_COUNT_HW_CACHE_OP_MAX, &len);
42661c45981SPaul Mackerras 		if (cache_op >= 0) {
427c754c382SArnaldo Carvalho de Melo 			if (!evsel__is_cache_op_valid(cache_type, cache_op))
42889812fc8SJiri Olsa 				return -EINVAL;
42970c90e4aSIan Rogers 			str += len + 1;
43070c90e4aSIan Rogers 		} else {
431c64e85e1SArnaldo Carvalho de Melo 			cache_result = parse_aliases(str, evsel__hw_cache_result,
43270c90e4aSIan Rogers 						PERF_COUNT_HW_CACHE_RESULT_MAX, &len);
43361c45981SPaul Mackerras 			if (cache_result >= 0)
43470c90e4aSIan Rogers 				str += len + 1;
43570c90e4aSIan Rogers 		}
43670c90e4aSIan Rogers 	}
43770c90e4aSIan Rogers 	if (str < name_end) {
43870c90e4aSIan Rogers 		if (cache_op < 0) {
43970c90e4aSIan Rogers 			cache_op = parse_aliases(str, evsel__hw_cache_op,
44070c90e4aSIan Rogers 						PERF_COUNT_HW_CACHE_OP_MAX, &len);
44170c90e4aSIan Rogers 			if (cache_op >= 0) {
44270c90e4aSIan Rogers 				if (!evsel__is_cache_op_valid(cache_type, cache_op))
44370c90e4aSIan Rogers 					return -EINVAL;
44470c90e4aSIan Rogers 			}
44570c90e4aSIan Rogers 		} else if (cache_result < 0) {
44670c90e4aSIan Rogers 			cache_result = parse_aliases(str, evsel__hw_cache_result,
44770c90e4aSIan Rogers 						PERF_COUNT_HW_CACHE_RESULT_MAX, &len);
44861c45981SPaul Mackerras 		}
44961c45981SPaul Mackerras 	}
45061c45981SPaul Mackerras 
45186470930SIngo Molnar 	/*
45286470930SIngo Molnar 	 * Fall back to reads:
45386470930SIngo Molnar 	 */
4548953645fSIngo Molnar 	if (cache_op == -1)
4558953645fSIngo Molnar 		cache_op = PERF_COUNT_HW_CACHE_OP_READ;
45686470930SIngo Molnar 
45786470930SIngo Molnar 	/*
45886470930SIngo Molnar 	 * Fall back to accesses:
45986470930SIngo Molnar 	 */
46086470930SIngo Molnar 	if (cache_result == -1)
46186470930SIngo Molnar 		cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS;
46286470930SIngo Molnar 
4636fd1e519SIan Rogers 	*config = ((__u64)pmu_type << PERF_PMU_TYPE_SHIFT) |
4646fd1e519SIan Rogers 		cache_type | (cache_op << 8) | (cache_result << 16);
4656fd1e519SIan Rogers 	return 0;
4666fd1e519SIan Rogers }
4676fd1e519SIan Rogers 
468411ad22eSIan Rogers /**
469411ad22eSIan Rogers  * parse_events__filter_pmu - returns false if a wildcard PMU should be
470411ad22eSIan Rogers  *                            considered, true if it should be filtered.
471411ad22eSIan Rogers  */
472411ad22eSIan Rogers bool parse_events__filter_pmu(const struct parse_events_state *parse_state,
473411ad22eSIan Rogers 			      const struct perf_pmu *pmu)
474411ad22eSIan Rogers {
475411ad22eSIan Rogers 	if (parse_state->pmu_filter == NULL)
476411ad22eSIan Rogers 		return false;
477411ad22eSIan Rogers 
478411ad22eSIan Rogers 	if (pmu->name == NULL)
479411ad22eSIan Rogers 		return true;
480411ad22eSIan Rogers 
481411ad22eSIan Rogers 	return strcmp(parse_state->pmu_filter, pmu->name) != 0;
482411ad22eSIan Rogers }
483411ad22eSIan Rogers 
4846fd1e519SIan Rogers int parse_events_add_cache(struct list_head *list, int *idx, const char *name,
485411ad22eSIan Rogers 			   struct parse_events_state *parse_state,
4862bdf4d7eSIan Rogers 			   struct list_head *head_config)
4876fd1e519SIan Rogers {
4882bdf4d7eSIan Rogers 	struct perf_pmu *pmu = NULL;
4892bdf4d7eSIan Rogers 	bool found_supported = false;
4902bdf4d7eSIan Rogers 	const char *config_name = get_config_name(head_config);
4912bdf4d7eSIan Rogers 	const char *metric_id = get_config_metric_id(head_config);
4926fd1e519SIan Rogers 
4932bdf4d7eSIan Rogers 	while ((pmu = perf_pmu__scan(pmu)) != NULL) {
4942bdf4d7eSIan Rogers 		LIST_HEAD(config_terms);
4952bdf4d7eSIan Rogers 		struct perf_event_attr attr;
4962bdf4d7eSIan Rogers 		int ret;
4972bdf4d7eSIan Rogers 
4982bdf4d7eSIan Rogers 		/* Skip unsupported PMUs. */
4992bdf4d7eSIan Rogers 		if (!perf_pmu__supports_legacy_cache(pmu))
5002bdf4d7eSIan Rogers 			continue;
5016fd1e519SIan Rogers 
502411ad22eSIan Rogers 		if (parse_events__filter_pmu(parse_state, pmu))
503411ad22eSIan Rogers 			continue;
504411ad22eSIan Rogers 
50589812fc8SJiri Olsa 		memset(&attr, 0, sizeof(attr));
50689812fc8SJiri Olsa 		attr.type = PERF_TYPE_HW_CACHE;
5072bdf4d7eSIan Rogers 
5082bdf4d7eSIan Rogers 		ret = parse_events__decode_legacy_cache(name, pmu->type, &attr.config);
5096fd1e519SIan Rogers 		if (ret)
5106fd1e519SIan Rogers 			return ret;
51143d0b978SWang Nan 
5122bdf4d7eSIan Rogers 		found_supported = true;
5132bdf4d7eSIan Rogers 
51443d0b978SWang Nan 		if (head_config) {
515411ad22eSIan Rogers 			if (config_attr(&attr, head_config, parse_state->error, config_term_common))
51643d0b978SWang Nan 				return -EINVAL;
51743d0b978SWang Nan 
51843d0b978SWang Nan 			if (get_config_terms(head_config, &config_terms))
51943d0b978SWang Nan 				return -ENOMEM;
52043d0b978SWang Nan 		}
52130def61fSJin Yao 
5222bdf4d7eSIan Rogers 		if (__add_event(list, idx, &attr, /*init_attr*/true, config_name ?: name,
5232bdf4d7eSIan Rogers 				metric_id, pmu, &config_terms, /*auto_merge_stats=*/false,
5242bdf4d7eSIan Rogers 				/*cpu_list=*/NULL) == NULL)
5252bdf4d7eSIan Rogers 			return -ENOMEM;
52630def61fSJin Yao 
52799fc5941SAdrian Hunter 		free_config_terms(&config_terms);
5282bdf4d7eSIan Rogers 	}
5292bdf4d7eSIan Rogers 	return found_supported ? 0 : -EINVAL;
53086470930SIngo Molnar }
53186470930SIngo Molnar 
532378ef0f5SIan Rogers #ifdef HAVE_LIBTRACEEVENT
533272ed29aSJiri Olsa static void tracepoint_error(struct parse_events_error *e, int err,
5348c619d6aSWang Nan 			     const char *sys, const char *name)
53519658171SJiri Olsa {
5364584f084SIan Rogers 	const char *str;
53719658171SJiri Olsa 	char help[BUFSIZ];
53819658171SJiri Olsa 
539ec183d22SAdrian Hunter 	if (!e)
540ec183d22SAdrian Hunter 		return;
541ec183d22SAdrian Hunter 
54219658171SJiri Olsa 	/*
54319658171SJiri Olsa 	 * We get error directly from syscall errno ( > 0),
54419658171SJiri Olsa 	 * or from encoded pointer's error ( < 0).
54519658171SJiri Olsa 	 */
54619658171SJiri Olsa 	err = abs(err);
54719658171SJiri Olsa 
54819658171SJiri Olsa 	switch (err) {
54919658171SJiri Olsa 	case EACCES:
5504584f084SIan Rogers 		str = "can't access trace events";
55119658171SJiri Olsa 		break;
55219658171SJiri Olsa 	case ENOENT:
5534584f084SIan Rogers 		str = "unknown tracepoint";
55419658171SJiri Olsa 		break;
55519658171SJiri Olsa 	default:
5564584f084SIan Rogers 		str = "failed to add tracepoint";
55719658171SJiri Olsa 		break;
55819658171SJiri Olsa 	}
55919658171SJiri Olsa 
56019658171SJiri Olsa 	tracing_path__strerror_open_tp(err, help, sizeof(help), sys, name);
5616c191289SIan Rogers 	parse_events_error__handle(e, 0, strdup(str), strdup(help));
56219658171SJiri Olsa }
56319658171SJiri Olsa 
564c5cd8ac0SDavid Ahern static int add_tracepoint(struct list_head *list, int *idx,
5658c619d6aSWang Nan 			  const char *sys_name, const char *evt_name,
566272ed29aSJiri Olsa 			  struct parse_events_error *err,
567e637d177SHe Kuang 			  struct list_head *head_config)
568bcd3279fSFrederic Weisbecker {
5698f6725a2SArnaldo Carvalho de Melo 	struct evsel *evsel = evsel__newtp_idx(sys_name, evt_name, (*idx)++);
570bcd3279fSFrederic Weisbecker 
57119658171SJiri Olsa 	if (IS_ERR(evsel)) {
572272ed29aSJiri Olsa 		tracepoint_error(err, PTR_ERR(evsel), sys_name, evt_name);
5738dd2a131SJiri Olsa 		return PTR_ERR(evsel);
57419658171SJiri Olsa 	}
575bcd3279fSFrederic Weisbecker 
576e637d177SHe Kuang 	if (head_config) {
577e637d177SHe Kuang 		LIST_HEAD(config_terms);
578e637d177SHe Kuang 
579e637d177SHe Kuang 		if (get_config_terms(head_config, &config_terms))
580e637d177SHe Kuang 			return -ENOMEM;
581e637d177SHe Kuang 		list_splice(&config_terms, &evsel->config_terms);
582e637d177SHe Kuang 	}
583e637d177SHe Kuang 
584b27c4eceSJiri Olsa 	list_add_tail(&evsel->core.node, list);
58582fe1c29SArnaldo Carvalho de Melo 	return 0;
586bcd3279fSFrederic Weisbecker }
587bcd3279fSFrederic Weisbecker 
588c5cd8ac0SDavid Ahern static int add_tracepoint_multi_event(struct list_head *list, int *idx,
5898c619d6aSWang Nan 				      const char *sys_name, const char *evt_name,
590272ed29aSJiri Olsa 				      struct parse_events_error *err,
591e637d177SHe Kuang 				      struct list_head *head_config)
592bcd3279fSFrederic Weisbecker {
59325a7d914SArnaldo Carvalho de Melo 	char *evt_path;
594bcd3279fSFrederic Weisbecker 	struct dirent *evt_ent;
595bcd3279fSFrederic Weisbecker 	DIR *evt_dir;
59627bf90bfSJiri Olsa 	int ret = 0, found = 0;
597bcd3279fSFrederic Weisbecker 
59825a7d914SArnaldo Carvalho de Melo 	evt_path = get_events_file(sys_name);
59925a7d914SArnaldo Carvalho de Melo 	if (!evt_path) {
60025a7d914SArnaldo Carvalho de Melo 		tracepoint_error(err, errno, sys_name, evt_name);
60125a7d914SArnaldo Carvalho de Melo 		return -1;
60225a7d914SArnaldo Carvalho de Melo 	}
603bcd3279fSFrederic Weisbecker 	evt_dir = opendir(evt_path);
604bcd3279fSFrederic Weisbecker 	if (!evt_dir) {
60525a7d914SArnaldo Carvalho de Melo 		put_events_file(evt_path);
606272ed29aSJiri Olsa 		tracepoint_error(err, errno, sys_name, evt_name);
60789812fc8SJiri Olsa 		return -1;
608bcd3279fSFrederic Weisbecker 	}
609bcd3279fSFrederic Weisbecker 
61089812fc8SJiri Olsa 	while (!ret && (evt_ent = readdir(evt_dir))) {
611bcd3279fSFrederic Weisbecker 		if (!strcmp(evt_ent->d_name, ".")
612bcd3279fSFrederic Weisbecker 		    || !strcmp(evt_ent->d_name, "..")
613bcd3279fSFrederic Weisbecker 		    || !strcmp(evt_ent->d_name, "enable")
614bcd3279fSFrederic Weisbecker 		    || !strcmp(evt_ent->d_name, "filter"))
615bcd3279fSFrederic Weisbecker 			continue;
616bcd3279fSFrederic Weisbecker 
61789812fc8SJiri Olsa 		if (!strglobmatch(evt_ent->d_name, evt_name))
618fb1d2edfSMasami Hiramatsu 			continue;
619fb1d2edfSMasami Hiramatsu 
62027bf90bfSJiri Olsa 		found++;
62127bf90bfSJiri Olsa 
622e637d177SHe Kuang 		ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name,
623272ed29aSJiri Olsa 				     err, head_config);
624bcd3279fSFrederic Weisbecker 	}
625bcd3279fSFrederic Weisbecker 
62627bf90bfSJiri Olsa 	if (!found) {
62727bf90bfSJiri Olsa 		tracepoint_error(err, ENOENT, sys_name, evt_name);
62827bf90bfSJiri Olsa 		ret = -1;
62927bf90bfSJiri Olsa 	}
63027bf90bfSJiri Olsa 
63125a7d914SArnaldo Carvalho de Melo 	put_events_file(evt_path);
6320bd3f084SJiri Olsa 	closedir(evt_dir);
63389812fc8SJiri Olsa 	return ret;
634bcd3279fSFrederic Weisbecker }
635bcd3279fSFrederic Weisbecker 
636c5cd8ac0SDavid Ahern static int add_tracepoint_event(struct list_head *list, int *idx,
6378c619d6aSWang Nan 				const char *sys_name, const char *evt_name,
638272ed29aSJiri Olsa 				struct parse_events_error *err,
639e637d177SHe Kuang 				struct list_head *head_config)
640f35488f9SJiri Olsa {
641f35488f9SJiri Olsa 	return strpbrk(evt_name, "*?") ?
642e637d177SHe Kuang 	       add_tracepoint_multi_event(list, idx, sys_name, evt_name,
643272ed29aSJiri Olsa 					  err, head_config) :
644e637d177SHe Kuang 	       add_tracepoint(list, idx, sys_name, evt_name,
645272ed29aSJiri Olsa 			      err, head_config);
646f35488f9SJiri Olsa }
647f35488f9SJiri Olsa 
648c5cd8ac0SDavid Ahern static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
6498c619d6aSWang Nan 				    const char *sys_name, const char *evt_name,
650272ed29aSJiri Olsa 				    struct parse_events_error *err,
651e637d177SHe Kuang 				    struct list_head *head_config)
652f35488f9SJiri Olsa {
653f35488f9SJiri Olsa 	struct dirent *events_ent;
654f35488f9SJiri Olsa 	DIR *events_dir;
655f35488f9SJiri Olsa 	int ret = 0;
656f35488f9SJiri Olsa 
6577014e0e3SArnaldo Carvalho de Melo 	events_dir = tracing_events__opendir();
658f35488f9SJiri Olsa 	if (!events_dir) {
659272ed29aSJiri Olsa 		tracepoint_error(err, errno, sys_name, evt_name);
660f35488f9SJiri Olsa 		return -1;
661f35488f9SJiri Olsa 	}
662f35488f9SJiri Olsa 
663f35488f9SJiri Olsa 	while (!ret && (events_ent = readdir(events_dir))) {
664f35488f9SJiri Olsa 		if (!strcmp(events_ent->d_name, ".")
665f35488f9SJiri Olsa 		    || !strcmp(events_ent->d_name, "..")
666f35488f9SJiri Olsa 		    || !strcmp(events_ent->d_name, "enable")
667f35488f9SJiri Olsa 		    || !strcmp(events_ent->d_name, "header_event")
668f35488f9SJiri Olsa 		    || !strcmp(events_ent->d_name, "header_page"))
669f35488f9SJiri Olsa 			continue;
670f35488f9SJiri Olsa 
671f35488f9SJiri Olsa 		if (!strglobmatch(events_ent->d_name, sys_name))
672f35488f9SJiri Olsa 			continue;
673f35488f9SJiri Olsa 
674f35488f9SJiri Olsa 		ret = add_tracepoint_event(list, idx, events_ent->d_name,
675272ed29aSJiri Olsa 					   evt_name, err, head_config);
676f35488f9SJiri Olsa 	}
677f35488f9SJiri Olsa 
678f35488f9SJiri Olsa 	closedir(events_dir);
679f35488f9SJiri Olsa 	return ret;
680f35488f9SJiri Olsa }
681378ef0f5SIan Rogers #endif /* HAVE_LIBTRACEEVENT */
682f35488f9SJiri Olsa 
683c18cf78dSArnaldo Carvalho de Melo #ifdef HAVE_LIBBPF_SUPPORT
6844edf30e3SWang Nan struct __add_bpf_event_param {
6855d9cdc11SArnaldo Carvalho de Melo 	struct parse_events_state *parse_state;
6864edf30e3SWang Nan 	struct list_head *list;
68795088a59SWang Nan 	struct list_head *head_config;
6884edf30e3SWang Nan };
6894edf30e3SWang Nan 
690af4a0991SArnaldo Carvalho de Melo static int add_bpf_event(const char *group, const char *event, int fd, struct bpf_object *obj,
6914edf30e3SWang Nan 			 void *_param)
6924edf30e3SWang Nan {
6934edf30e3SWang Nan 	LIST_HEAD(new_evsels);
6944edf30e3SWang Nan 	struct __add_bpf_event_param *param = _param;
6955d9cdc11SArnaldo Carvalho de Melo 	struct parse_events_state *parse_state = param->parse_state;
6964edf30e3SWang Nan 	struct list_head *list = param->list;
69732dcd021SJiri Olsa 	struct evsel *pos;
6984edf30e3SWang Nan 	int err;
6992620b7e3SArnaldo Carvalho de Melo 	/*
7002620b7e3SArnaldo Carvalho de Melo 	 * Check if we should add the event, i.e. if it is a TP but starts with a '!',
7012620b7e3SArnaldo Carvalho de Melo 	 * then don't add the tracepoint, this will be used for something else, like
7022620b7e3SArnaldo Carvalho de Melo 	 * adding to a BPF_MAP_TYPE_PROG_ARRAY.
7032620b7e3SArnaldo Carvalho de Melo 	 *
7042620b7e3SArnaldo Carvalho de Melo 	 * See tools/perf/examples/bpf/augmented_raw_syscalls.c
7052620b7e3SArnaldo Carvalho de Melo 	 */
7062620b7e3SArnaldo Carvalho de Melo 	if (group[0] == '!')
7072620b7e3SArnaldo Carvalho de Melo 		return 0;
7084edf30e3SWang Nan 
7094edf30e3SWang Nan 	pr_debug("add bpf event %s:%s and attach bpf program %d\n",
710cd102d70SWang Nan 		 group, event, fd);
7114edf30e3SWang Nan 
7125d369a75SArnaldo Carvalho de Melo 	err = parse_events_add_tracepoint(&new_evsels, &parse_state->idx, group,
7135d369a75SArnaldo Carvalho de Melo 					  event, parse_state->error,
71495088a59SWang Nan 					  param->head_config);
7154edf30e3SWang Nan 	if (err) {
71632dcd021SJiri Olsa 		struct evsel *evsel, *tmp;
7174edf30e3SWang Nan 
7184edf30e3SWang Nan 		pr_debug("Failed to add BPF event %s:%s\n",
719cd102d70SWang Nan 			 group, event);
720b27c4eceSJiri Olsa 		list_for_each_entry_safe(evsel, tmp, &new_evsels, core.node) {
721b27c4eceSJiri Olsa 			list_del_init(&evsel->core.node);
7225eb2dd2aSJiri Olsa 			evsel__delete(evsel);
7234edf30e3SWang Nan 		}
7244edf30e3SWang Nan 		return err;
7254edf30e3SWang Nan 	}
726cd102d70SWang Nan 	pr_debug("adding %s:%s\n", group, event);
7274edf30e3SWang Nan 
728b27c4eceSJiri Olsa 	list_for_each_entry(pos, &new_evsels, core.node) {
7291f45b1d4SWang Nan 		pr_debug("adding %s:%s to %p\n",
730cd102d70SWang Nan 			 group, event, pos);
7311f45b1d4SWang Nan 		pos->bpf_fd = fd;
732af4a0991SArnaldo Carvalho de Melo 		pos->bpf_obj = obj;
7331f45b1d4SWang Nan 	}
7344edf30e3SWang Nan 	list_splice(&new_evsels, list);
7354edf30e3SWang Nan 	return 0;
7364edf30e3SWang Nan }
7374edf30e3SWang Nan 
7385d9cdc11SArnaldo Carvalho de Melo int parse_events_load_bpf_obj(struct parse_events_state *parse_state,
73984c86ca1SWang Nan 			      struct list_head *list,
74095088a59SWang Nan 			      struct bpf_object *obj,
74195088a59SWang Nan 			      struct list_head *head_config)
74284c86ca1SWang Nan {
74384c86ca1SWang Nan 	int err;
74484c86ca1SWang Nan 	char errbuf[BUFSIZ];
7455d9cdc11SArnaldo Carvalho de Melo 	struct __add_bpf_event_param param = {parse_state, list, head_config};
746aa3abf30SWang Nan 	static bool registered_unprobe_atexit = false;
74784c86ca1SWang Nan 
74884c86ca1SWang Nan 	if (IS_ERR(obj) || !obj) {
74984c86ca1SWang Nan 		snprintf(errbuf, sizeof(errbuf),
75084c86ca1SWang Nan 			 "Internal error: load bpf obj with NULL");
75184c86ca1SWang Nan 		err = -EINVAL;
75284c86ca1SWang Nan 		goto errout;
75384c86ca1SWang Nan 	}
75484c86ca1SWang Nan 
75584c86ca1SWang Nan 	/*
756aa3abf30SWang Nan 	 * Register atexit handler before calling bpf__probe() so
757aa3abf30SWang Nan 	 * bpf__probe() don't need to unprobe probe points its already
758aa3abf30SWang Nan 	 * created when failure.
759aa3abf30SWang Nan 	 */
760aa3abf30SWang Nan 	if (!registered_unprobe_atexit) {
761aa3abf30SWang Nan 		atexit(bpf__clear);
762aa3abf30SWang Nan 		registered_unprobe_atexit = true;
763aa3abf30SWang Nan 	}
764aa3abf30SWang Nan 
765aa3abf30SWang Nan 	err = bpf__probe(obj);
766aa3abf30SWang Nan 	if (err) {
767aa3abf30SWang Nan 		bpf__strerror_probe(obj, err, errbuf, sizeof(errbuf));
768aa3abf30SWang Nan 		goto errout;
769aa3abf30SWang Nan 	}
770aa3abf30SWang Nan 
7711e5e3ee8SWang Nan 	err = bpf__load(obj);
7721e5e3ee8SWang Nan 	if (err) {
7731e5e3ee8SWang Nan 		bpf__strerror_load(obj, err, errbuf, sizeof(errbuf));
7741e5e3ee8SWang Nan 		goto errout;
7751e5e3ee8SWang Nan 	}
7761e5e3ee8SWang Nan 
777cd102d70SWang Nan 	err = bpf__foreach_event(obj, add_bpf_event, &param);
7784edf30e3SWang Nan 	if (err) {
7794edf30e3SWang Nan 		snprintf(errbuf, sizeof(errbuf),
7804edf30e3SWang Nan 			 "Attach events in BPF object failed");
7814edf30e3SWang Nan 		goto errout;
7824edf30e3SWang Nan 	}
7834edf30e3SWang Nan 
7844edf30e3SWang Nan 	return 0;
78584c86ca1SWang Nan errout:
7866c191289SIan Rogers 	parse_events_error__handle(parse_state->error, 0,
7875f634c8eSIan Rogers 				strdup(errbuf), strdup("(add -v to see detail)"));
78884c86ca1SWang Nan 	return err;
78984c86ca1SWang Nan }
79084c86ca1SWang Nan 
791a34f3be7SWang Nan static int
7925d9cdc11SArnaldo Carvalho de Melo parse_events_config_bpf(struct parse_events_state *parse_state,
793a34f3be7SWang Nan 			struct bpf_object *obj,
794a34f3be7SWang Nan 			struct list_head *head_config)
795a34f3be7SWang Nan {
796a34f3be7SWang Nan 	struct parse_events_term *term;
797a34f3be7SWang Nan 	int error_pos;
798a34f3be7SWang Nan 
799a34f3be7SWang Nan 	if (!head_config || list_empty(head_config))
800a34f3be7SWang Nan 		return 0;
801a34f3be7SWang Nan 
802a34f3be7SWang Nan 	list_for_each_entry(term, head_config, list) {
803a34f3be7SWang Nan 		int err;
804a34f3be7SWang Nan 
805a34f3be7SWang Nan 		if (term->type_term != PARSE_EVENTS__TERM_TYPE_USER) {
8066c191289SIan Rogers 			parse_events_error__handle(parse_state->error, term->err_term,
8075f634c8eSIan Rogers 						strdup("Invalid config term for BPF object"),
8085f634c8eSIan Rogers 						NULL);
809a34f3be7SWang Nan 			return -EINVAL;
810a34f3be7SWang Nan 		}
811a34f3be7SWang Nan 
8125d9cdc11SArnaldo Carvalho de Melo 		err = bpf__config_obj(obj, term, parse_state->evlist, &error_pos);
813a34f3be7SWang Nan 		if (err) {
8145f634c8eSIan Rogers 			char errbuf[BUFSIZ];
8155f634c8eSIan Rogers 			int idx;
8165f634c8eSIan Rogers 
8175d9cdc11SArnaldo Carvalho de Melo 			bpf__strerror_config_obj(obj, term, parse_state->evlist,
818a34f3be7SWang Nan 						 &error_pos, err, errbuf,
819a34f3be7SWang Nan 						 sizeof(errbuf));
8205f634c8eSIan Rogers 
8215f634c8eSIan Rogers 			if (err == -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE)
8225f634c8eSIan Rogers 				idx = term->err_val;
8235f634c8eSIan Rogers 			else
8245f634c8eSIan Rogers 				idx = term->err_term + error_pos;
8255f634c8eSIan Rogers 
8266c191289SIan Rogers 			parse_events_error__handle(parse_state->error, idx,
8275f634c8eSIan Rogers 						strdup(errbuf),
8285f634c8eSIan Rogers 						strdup(
8297630b3e2SWang Nan "Hint:\tValid config terms:\n"
830e571e029SWang Nan "     \tmap:[<arraymap>].value<indices>=[value]\n"
831e571e029SWang Nan "     \tmap:[<eventmap>].event<indices>=[event]\n"
8327630b3e2SWang Nan "\n"
833e571e029SWang Nan "     \twhere <indices> is something like [0,3...5] or [all]\n"
8345f634c8eSIan Rogers "     \t(add -v to see detail)"));
835a34f3be7SWang Nan 			return err;
836a34f3be7SWang Nan 		}
837a34f3be7SWang Nan 	}
838a34f3be7SWang Nan 	return 0;
839a34f3be7SWang Nan }
840a34f3be7SWang Nan 
84195088a59SWang Nan /*
84295088a59SWang Nan  * Split config terms:
84395088a59SWang Nan  * perf record -e bpf.c/call-graph=fp,map:array.value[0]=1/ ...
84495088a59SWang Nan  *  'call-graph=fp' is 'evt config', should be applied to each
84595088a59SWang Nan  *  events in bpf.c.
84695088a59SWang Nan  * 'map:array.value[0]=1' is 'obj config', should be processed
84795088a59SWang Nan  * with parse_events_config_bpf.
84895088a59SWang Nan  *
84995088a59SWang Nan  * Move object config terms from the first list to obj_head_config.
85095088a59SWang Nan  */
85195088a59SWang Nan static void
85295088a59SWang Nan split_bpf_config_terms(struct list_head *evt_head_config,
85395088a59SWang Nan 		       struct list_head *obj_head_config)
85495088a59SWang Nan {
85595088a59SWang Nan 	struct parse_events_term *term, *temp;
85695088a59SWang Nan 
85795088a59SWang Nan 	/*
8584d39c89fSIngo Molnar 	 * Currently, all possible user config term
85995088a59SWang Nan 	 * belong to bpf object. parse_events__is_hardcoded_term()
8604d39c89fSIngo Molnar 	 * happens to be a good flag.
86195088a59SWang Nan 	 *
86295088a59SWang Nan 	 * See parse_events_config_bpf() and
86395088a59SWang Nan 	 * config_term_tracepoint().
86495088a59SWang Nan 	 */
86595088a59SWang Nan 	list_for_each_entry_safe(term, temp, evt_head_config, list)
86695088a59SWang Nan 		if (!parse_events__is_hardcoded_term(term))
86795088a59SWang Nan 			list_move_tail(&term->list, obj_head_config);
86895088a59SWang Nan }
86995088a59SWang Nan 
8705d9cdc11SArnaldo Carvalho de Melo int parse_events_load_bpf(struct parse_events_state *parse_state,
87184c86ca1SWang Nan 			  struct list_head *list,
872d509db04SWang Nan 			  char *bpf_file_name,
873a34f3be7SWang Nan 			  bool source,
874a34f3be7SWang Nan 			  struct list_head *head_config)
87584c86ca1SWang Nan {
876a34f3be7SWang Nan 	int err;
87795088a59SWang Nan 	struct bpf_object *obj;
87895088a59SWang Nan 	LIST_HEAD(obj_head_config);
87995088a59SWang Nan 
88095088a59SWang Nan 	if (head_config)
88195088a59SWang Nan 		split_bpf_config_terms(head_config, &obj_head_config);
88284c86ca1SWang Nan 
883d509db04SWang Nan 	obj = bpf__prepare_load(bpf_file_name, source);
8846371ca3bSWang Nan 	if (IS_ERR(obj)) {
88584c86ca1SWang Nan 		char errbuf[BUFSIZ];
88684c86ca1SWang Nan 
8876371ca3bSWang Nan 		err = PTR_ERR(obj);
88884c86ca1SWang Nan 
88984c86ca1SWang Nan 		if (err == -ENOTSUP)
89084c86ca1SWang Nan 			snprintf(errbuf, sizeof(errbuf),
89184c86ca1SWang Nan 				 "BPF support is not compiled");
89284c86ca1SWang Nan 		else
893d3e0ce39SWang Nan 			bpf__strerror_prepare_load(bpf_file_name,
894d3e0ce39SWang Nan 						   source,
895d3e0ce39SWang Nan 						   -err, errbuf,
896d3e0ce39SWang Nan 						   sizeof(errbuf));
89784c86ca1SWang Nan 
8986c191289SIan Rogers 		parse_events_error__handle(parse_state->error, 0,
8995f634c8eSIan Rogers 					strdup(errbuf), strdup("(add -v to see detail)"));
90084c86ca1SWang Nan 		return err;
90184c86ca1SWang Nan 	}
90284c86ca1SWang Nan 
9035d9cdc11SArnaldo Carvalho de Melo 	err = parse_events_load_bpf_obj(parse_state, list, obj, head_config);
904a34f3be7SWang Nan 	if (err)
905a34f3be7SWang Nan 		return err;
9065d9cdc11SArnaldo Carvalho de Melo 	err = parse_events_config_bpf(parse_state, obj, &obj_head_config);
90795088a59SWang Nan 
90895088a59SWang Nan 	/*
90995088a59SWang Nan 	 * Caller doesn't know anything about obj_head_config,
9104d39c89fSIngo Molnar 	 * so combine them together again before returning.
91195088a59SWang Nan 	 */
91295088a59SWang Nan 	if (head_config)
91395088a59SWang Nan 		list_splice_tail(&obj_head_config, head_config);
91495088a59SWang Nan 	return err;
91584c86ca1SWang Nan }
916c18cf78dSArnaldo Carvalho de Melo #else // HAVE_LIBBPF_SUPPORT
917c18cf78dSArnaldo Carvalho de Melo int parse_events_load_bpf_obj(struct parse_events_state *parse_state,
918c18cf78dSArnaldo Carvalho de Melo 			      struct list_head *list __maybe_unused,
919c18cf78dSArnaldo Carvalho de Melo 			      struct bpf_object *obj __maybe_unused,
920c18cf78dSArnaldo Carvalho de Melo 			      struct list_head *head_config __maybe_unused)
921c18cf78dSArnaldo Carvalho de Melo {
9226c191289SIan Rogers 	parse_events_error__handle(parse_state->error, 0,
923c18cf78dSArnaldo Carvalho de Melo 				   strdup("BPF support is not compiled"),
924c18cf78dSArnaldo Carvalho de Melo 				   strdup("Make sure libbpf-devel is available at build time."));
925c18cf78dSArnaldo Carvalho de Melo 	return -ENOTSUP;
926c18cf78dSArnaldo Carvalho de Melo }
927c18cf78dSArnaldo Carvalho de Melo 
928c18cf78dSArnaldo Carvalho de Melo int parse_events_load_bpf(struct parse_events_state *parse_state,
929c18cf78dSArnaldo Carvalho de Melo 			  struct list_head *list __maybe_unused,
930c18cf78dSArnaldo Carvalho de Melo 			  char *bpf_file_name __maybe_unused,
931c18cf78dSArnaldo Carvalho de Melo 			  bool source __maybe_unused,
932c18cf78dSArnaldo Carvalho de Melo 			  struct list_head *head_config __maybe_unused)
933c18cf78dSArnaldo Carvalho de Melo {
9346c191289SIan Rogers 	parse_events_error__handle(parse_state->error, 0,
935c18cf78dSArnaldo Carvalho de Melo 				   strdup("BPF support is not compiled"),
936c18cf78dSArnaldo Carvalho de Melo 				   strdup("Make sure libbpf-devel is available at build time."));
937c18cf78dSArnaldo Carvalho de Melo 	return -ENOTSUP;
938c18cf78dSArnaldo Carvalho de Melo }
939c18cf78dSArnaldo Carvalho de Melo #endif // HAVE_LIBBPF_SUPPORT
94084c86ca1SWang Nan 
94189812fc8SJiri Olsa static int
94289812fc8SJiri Olsa parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
9431b290d67SFrederic Weisbecker {
9441b290d67SFrederic Weisbecker 	int i;
9451b290d67SFrederic Weisbecker 
9461b290d67SFrederic Weisbecker 	for (i = 0; i < 3; i++) {
94789812fc8SJiri Olsa 		if (!type || !type[i])
9481b290d67SFrederic Weisbecker 			break;
9491b290d67SFrederic Weisbecker 
9507582732fSJiri Olsa #define CHECK_SET_TYPE(bit)		\
9517582732fSJiri Olsa do {					\
9527582732fSJiri Olsa 	if (attr->bp_type & bit)	\
9537582732fSJiri Olsa 		return -EINVAL;		\
9547582732fSJiri Olsa 	else				\
9557582732fSJiri Olsa 		attr->bp_type |= bit;	\
9567582732fSJiri Olsa } while (0)
9577582732fSJiri Olsa 
9581b290d67SFrederic Weisbecker 		switch (type[i]) {
9591b290d67SFrederic Weisbecker 		case 'r':
9607582732fSJiri Olsa 			CHECK_SET_TYPE(HW_BREAKPOINT_R);
9611b290d67SFrederic Weisbecker 			break;
9621b290d67SFrederic Weisbecker 		case 'w':
9637582732fSJiri Olsa 			CHECK_SET_TYPE(HW_BREAKPOINT_W);
9641b290d67SFrederic Weisbecker 			break;
9651b290d67SFrederic Weisbecker 		case 'x':
9667582732fSJiri Olsa 			CHECK_SET_TYPE(HW_BREAKPOINT_X);
9671b290d67SFrederic Weisbecker 			break;
9681b290d67SFrederic Weisbecker 		default:
96989812fc8SJiri Olsa 			return -EINVAL;
9701b290d67SFrederic Weisbecker 		}
9711b290d67SFrederic Weisbecker 	}
97289812fc8SJiri Olsa 
9737582732fSJiri Olsa #undef CHECK_SET_TYPE
9747582732fSJiri Olsa 
9751b290d67SFrederic Weisbecker 	if (!attr->bp_type) /* Default */
9761b290d67SFrederic Weisbecker 		attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
9771b290d67SFrederic Weisbecker 
97889812fc8SJiri Olsa 	return 0;
9791b290d67SFrederic Weisbecker }
9801b290d67SFrederic Weisbecker 
981c5cd8ac0SDavid Ahern int parse_events_add_breakpoint(struct list_head *list, int *idx,
982aa98d848SIan Rogers 				u64 addr, char *type, u64 len)
9831b290d67SFrederic Weisbecker {
98489812fc8SJiri Olsa 	struct perf_event_attr attr;
9851b290d67SFrederic Weisbecker 
98689812fc8SJiri Olsa 	memset(&attr, 0, sizeof(attr));
987aa98d848SIan Rogers 	attr.bp_addr = addr;
9881b290d67SFrederic Weisbecker 
98989812fc8SJiri Olsa 	if (parse_breakpoint_type(type, &attr))
99089812fc8SJiri Olsa 		return -EINVAL;
9911b290d67SFrederic Weisbecker 
9923741eb9fSJacob Shin 	/* Provide some defaults if len is not specified */
9933741eb9fSJacob Shin 	if (!len) {
99489812fc8SJiri Olsa 		if (attr.bp_type == HW_BREAKPOINT_X)
9953741eb9fSJacob Shin 			len = sizeof(long);
996aa59a485SFrederic Weisbecker 		else
9973741eb9fSJacob Shin 			len = HW_BREAKPOINT_LEN_4;
9983741eb9fSJacob Shin 	}
9993741eb9fSJacob Shin 
10003741eb9fSJacob Shin 	attr.bp_len = len;
1001aa59a485SFrederic Weisbecker 
100289812fc8SJiri Olsa 	attr.type = PERF_TYPE_BREAKPOINT;
10034a841d65SJovi Zhang 	attr.sample_period = 1;
10041b290d67SFrederic Weisbecker 
10052b62b3a6SIan Rogers 	return add_event(list, idx, &attr, /*name=*/NULL, /*mertic_id=*/NULL,
10062b62b3a6SIan Rogers 			 /*config_terms=*/NULL);
10071b290d67SFrederic Weisbecker }
10081b290d67SFrederic Weisbecker 
10093b0e371cSJiri Olsa static int check_type_val(struct parse_events_term *term,
10103b0e371cSJiri Olsa 			  struct parse_events_error *err,
10113b0e371cSJiri Olsa 			  int type)
10123b0e371cSJiri Olsa {
10133b0e371cSJiri Olsa 	if (type == term->type_val)
10143b0e371cSJiri Olsa 		return 0;
10153b0e371cSJiri Olsa 
10163b0e371cSJiri Olsa 	if (err) {
10176c191289SIan Rogers 		parse_events_error__handle(err, term->err_val,
1018448d732cSIan Rogers 					type == PARSE_EVENTS__TERM_TYPE_NUM
1019448d732cSIan Rogers 					? strdup("expected numeric value")
1020448d732cSIan Rogers 					: strdup("expected string value"),
1021448d732cSIan Rogers 					NULL);
10223b0e371cSJiri Olsa 	}
10233b0e371cSJiri Olsa 	return -EINVAL;
10243b0e371cSJiri Olsa }
10253b0e371cSJiri Olsa 
102617cb5f84SWang Nan /*
102717cb5f84SWang Nan  * Update according to parse-events.l
102817cb5f84SWang Nan  */
102917cb5f84SWang Nan static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = {
103017cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_USER]			= "<sysfs term>",
103117cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_CONFIG]		= "config",
103217cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_CONFIG1]		= "config1",
103317cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_CONFIG2]		= "config2",
1034204e7c49SRob Herring 	[PARSE_EVENTS__TERM_TYPE_CONFIG3]		= "config3",
103517cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_NAME]			= "name",
103617cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD]		= "period",
103717cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ]		= "freq",
103817cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE]	= "branch_type",
103917cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_TIME]			= "time",
104017cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_CALLGRAPH]		= "call-graph",
104117cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_STACKSIZE]		= "stack-size",
104217cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_NOINHERIT]		= "no-inherit",
104317cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_INHERIT]		= "inherit",
1044792d48b4SArnaldo Carvalho de Melo 	[PARSE_EVENTS__TERM_TYPE_MAX_STACK]		= "max-stack",
10452fda5adaSArnaldo Carvalho de Melo 	[PARSE_EVENTS__TERM_TYPE_MAX_EVENTS]		= "nr",
1046626a6b78SWang Nan 	[PARSE_EVENTS__TERM_TYPE_OVERWRITE]		= "overwrite",
1047626a6b78SWang Nan 	[PARSE_EVENTS__TERM_TYPE_NOOVERWRITE]		= "no-overwrite",
1048dd60fba7SMathieu Poirier 	[PARSE_EVENTS__TERM_TYPE_DRV_CFG]		= "driver-config",
1049064b4e82SJin Yao 	[PARSE_EVENTS__TERM_TYPE_PERCORE]		= "percore",
10501b992154SAdrian Hunter 	[PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT]		= "aux-output",
1051eb7a52d4SAdrian Hunter 	[PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE]	= "aux-sample-size",
10522b62b3a6SIan Rogers 	[PARSE_EVENTS__TERM_TYPE_METRIC_ID]		= "metric-id",
105370c90e4aSIan Rogers 	[PARSE_EVENTS__TERM_TYPE_RAW]                   = "raw",
10546fd1e519SIan Rogers 	[PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE]          = "legacy-cache",
10555ea8f2ccSIan Rogers 	[PARSE_EVENTS__TERM_TYPE_HARDWARE]              = "hardware",
105617cb5f84SWang Nan };
105717cb5f84SWang Nan 
10581669e509SWang Nan static bool config_term_shrinked;
10591669e509SWang Nan 
10601669e509SWang Nan static bool
10611669e509SWang Nan config_term_avail(int term_type, struct parse_events_error *err)
10621669e509SWang Nan {
1063448d732cSIan Rogers 	char *err_str;
1064448d732cSIan Rogers 
10651669e509SWang Nan 	if (term_type < 0 || term_type >= __PARSE_EVENTS__TERM_TYPE_NR) {
10666c191289SIan Rogers 		parse_events_error__handle(err, -1,
1067448d732cSIan Rogers 					strdup("Invalid term_type"), NULL);
10681669e509SWang Nan 		return false;
10691669e509SWang Nan 	}
10701669e509SWang Nan 	if (!config_term_shrinked)
10711669e509SWang Nan 		return true;
10721669e509SWang Nan 
10731669e509SWang Nan 	switch (term_type) {
10741669e509SWang Nan 	case PARSE_EVENTS__TERM_TYPE_CONFIG:
10751669e509SWang Nan 	case PARSE_EVENTS__TERM_TYPE_CONFIG1:
10761669e509SWang Nan 	case PARSE_EVENTS__TERM_TYPE_CONFIG2:
1077204e7c49SRob Herring 	case PARSE_EVENTS__TERM_TYPE_CONFIG3:
10781669e509SWang Nan 	case PARSE_EVENTS__TERM_TYPE_NAME:
10792b62b3a6SIan Rogers 	case PARSE_EVENTS__TERM_TYPE_METRIC_ID:
108006835545SSukadev Bhattiprolu 	case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
1081064b4e82SJin Yao 	case PARSE_EVENTS__TERM_TYPE_PERCORE:
10821669e509SWang Nan 		return true;
10831669e509SWang Nan 	default:
10841669e509SWang Nan 		if (!err)
10851669e509SWang Nan 			return false;
10861669e509SWang Nan 
10871669e509SWang Nan 		/* term_type is validated so indexing is safe */
1088448d732cSIan Rogers 		if (asprintf(&err_str, "'%s' is not usable in 'perf stat'",
1089448d732cSIan Rogers 				config_term_names[term_type]) >= 0)
10906c191289SIan Rogers 			parse_events_error__handle(err, -1, err_str, NULL);
10911669e509SWang Nan 		return false;
10921669e509SWang Nan 	}
10931669e509SWang Nan }
10941669e509SWang Nan 
10951669e509SWang Nan void parse_events__shrink_config_terms(void)
10961669e509SWang Nan {
10971669e509SWang Nan 	config_term_shrinked = true;
10981669e509SWang Nan }
10991669e509SWang Nan 
11000b8891a8SHe Kuang static int config_term_common(struct perf_event_attr *attr,
11013b0e371cSJiri Olsa 			      struct parse_events_term *term,
11023b0e371cSJiri Olsa 			      struct parse_events_error *err)
11038f707d84SJiri Olsa {
110416fa7e82SJiri Olsa #define CHECK_TYPE_VAL(type)						   \
110516fa7e82SJiri Olsa do {									   \
11063b0e371cSJiri Olsa 	if (check_type_val(term, err, PARSE_EVENTS__TERM_TYPE_ ## type)) \
110716fa7e82SJiri Olsa 		return -EINVAL;						   \
110816fa7e82SJiri Olsa } while (0)
110916fa7e82SJiri Olsa 
111016fa7e82SJiri Olsa 	switch (term->type_term) {
11118f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_CONFIG:
111216fa7e82SJiri Olsa 		CHECK_TYPE_VAL(NUM);
11138f707d84SJiri Olsa 		attr->config = term->val.num;
11148f707d84SJiri Olsa 		break;
11158f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_CONFIG1:
111616fa7e82SJiri Olsa 		CHECK_TYPE_VAL(NUM);
11178f707d84SJiri Olsa 		attr->config1 = term->val.num;
11188f707d84SJiri Olsa 		break;
11198f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_CONFIG2:
112016fa7e82SJiri Olsa 		CHECK_TYPE_VAL(NUM);
11218f707d84SJiri Olsa 		attr->config2 = term->val.num;
11228f707d84SJiri Olsa 		break;
1123204e7c49SRob Herring 	case PARSE_EVENTS__TERM_TYPE_CONFIG3:
1124204e7c49SRob Herring 		CHECK_TYPE_VAL(NUM);
1125204e7c49SRob Herring 		attr->config3 = term->val.num;
1126204e7c49SRob Herring 		break;
11278f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
112816fa7e82SJiri Olsa 		CHECK_TYPE_VAL(NUM);
11298f707d84SJiri Olsa 		break;
113009af2a55SNamhyung Kim 	case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ:
113109af2a55SNamhyung Kim 		CHECK_TYPE_VAL(NUM);
113209af2a55SNamhyung Kim 		break;
11338f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE:
1134ac12f676SAndi Kleen 		CHECK_TYPE_VAL(STR);
1135ac12f676SAndi Kleen 		if (strcmp(term->val.str, "no") &&
1136448d732cSIan Rogers 		    parse_branch_str(term->val.str,
1137448d732cSIan Rogers 				    &attr->branch_sample_type)) {
11386c191289SIan Rogers 			parse_events_error__handle(err, term->err_val,
1139448d732cSIan Rogers 					strdup("invalid branch sample type"),
1140448d732cSIan Rogers 					NULL);
1141ac12f676SAndi Kleen 			return -EINVAL;
1142ac12f676SAndi Kleen 		}
11438f707d84SJiri Olsa 		break;
114432067712SKan Liang 	case PARSE_EVENTS__TERM_TYPE_TIME:
114532067712SKan Liang 		CHECK_TYPE_VAL(NUM);
114632067712SKan Liang 		if (term->val.num > 1) {
11476c191289SIan Rogers 			parse_events_error__handle(err, term->err_val,
1148448d732cSIan Rogers 						strdup("expected 0 or 1"),
1149448d732cSIan Rogers 						NULL);
115032067712SKan Liang 			return -EINVAL;
115132067712SKan Liang 		}
115232067712SKan Liang 		break;
1153d457c963SKan Liang 	case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
1154d457c963SKan Liang 		CHECK_TYPE_VAL(STR);
1155d457c963SKan Liang 		break;
1156d457c963SKan Liang 	case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
1157d457c963SKan Liang 		CHECK_TYPE_VAL(NUM);
1158d457c963SKan Liang 		break;
1159374ce938SWang Nan 	case PARSE_EVENTS__TERM_TYPE_INHERIT:
1160374ce938SWang Nan 		CHECK_TYPE_VAL(NUM);
1161374ce938SWang Nan 		break;
1162374ce938SWang Nan 	case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
1163374ce938SWang Nan 		CHECK_TYPE_VAL(NUM);
1164374ce938SWang Nan 		break;
1165626a6b78SWang Nan 	case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
1166626a6b78SWang Nan 		CHECK_TYPE_VAL(NUM);
1167626a6b78SWang Nan 		break;
1168626a6b78SWang Nan 	case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE:
1169626a6b78SWang Nan 		CHECK_TYPE_VAL(NUM);
1170626a6b78SWang Nan 		break;
11716b5fc39bSJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_NAME:
11726b5fc39bSJiri Olsa 		CHECK_TYPE_VAL(STR);
11736b5fc39bSJiri Olsa 		break;
11742b62b3a6SIan Rogers 	case PARSE_EVENTS__TERM_TYPE_METRIC_ID:
11752b62b3a6SIan Rogers 		CHECK_TYPE_VAL(STR);
11762b62b3a6SIan Rogers 		break;
117770c90e4aSIan Rogers 	case PARSE_EVENTS__TERM_TYPE_RAW:
117870c90e4aSIan Rogers 		CHECK_TYPE_VAL(STR);
117970c90e4aSIan Rogers 		break;
1180792d48b4SArnaldo Carvalho de Melo 	case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
1181792d48b4SArnaldo Carvalho de Melo 		CHECK_TYPE_VAL(NUM);
1182792d48b4SArnaldo Carvalho de Melo 		break;
11832fda5adaSArnaldo Carvalho de Melo 	case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS:
11842fda5adaSArnaldo Carvalho de Melo 		CHECK_TYPE_VAL(NUM);
11852fda5adaSArnaldo Carvalho de Melo 		break;
1186064b4e82SJin Yao 	case PARSE_EVENTS__TERM_TYPE_PERCORE:
1187064b4e82SJin Yao 		CHECK_TYPE_VAL(NUM);
1188064b4e82SJin Yao 		if ((unsigned int)term->val.num > 1) {
11896c191289SIan Rogers 			parse_events_error__handle(err, term->err_val,
1190448d732cSIan Rogers 						strdup("expected 0 or 1"),
1191448d732cSIan Rogers 						NULL);
1192064b4e82SJin Yao 			return -EINVAL;
1193064b4e82SJin Yao 		}
1194064b4e82SJin Yao 		break;
11951b992154SAdrian Hunter 	case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT:
11961b992154SAdrian Hunter 		CHECK_TYPE_VAL(NUM);
11971b992154SAdrian Hunter 		break;
1198eb7a52d4SAdrian Hunter 	case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE:
1199eb7a52d4SAdrian Hunter 		CHECK_TYPE_VAL(NUM);
1200eb7a52d4SAdrian Hunter 		if (term->val.num > UINT_MAX) {
12016c191289SIan Rogers 			parse_events_error__handle(err, term->err_val,
1202eb7a52d4SAdrian Hunter 						strdup("too big"),
1203eb7a52d4SAdrian Hunter 						NULL);
1204eb7a52d4SAdrian Hunter 			return -EINVAL;
1205eb7a52d4SAdrian Hunter 		}
1206eb7a52d4SAdrian Hunter 		break;
12078f707d84SJiri Olsa 	default:
12086c191289SIan Rogers 		parse_events_error__handle(err, term->err_term,
1209448d732cSIan Rogers 				strdup("unknown term"),
1210448d732cSIan Rogers 				parse_events_formats_error_string(NULL));
12118f707d84SJiri Olsa 		return -EINVAL;
12128f707d84SJiri Olsa 	}
121316fa7e82SJiri Olsa 
12141669e509SWang Nan 	/*
12154d39c89fSIngo Molnar 	 * Check term availability after basic checking so
12161669e509SWang Nan 	 * PARSE_EVENTS__TERM_TYPE_USER can be found and filtered.
12171669e509SWang Nan 	 *
12184d39c89fSIngo Molnar 	 * If check availability at the entry of this function,
12191669e509SWang Nan 	 * user will see "'<sysfs term>' is not usable in 'perf stat'"
12201669e509SWang Nan 	 * if an invalid config term is provided for legacy events
12211669e509SWang Nan 	 * (for example, instructions/badterm/...), which is confusing.
12221669e509SWang Nan 	 */
12231669e509SWang Nan 	if (!config_term_avail(term->type_term, err))
12241669e509SWang Nan 		return -EINVAL;
12258f707d84SJiri Olsa 	return 0;
122616fa7e82SJiri Olsa #undef CHECK_TYPE_VAL
12278f707d84SJiri Olsa }
12288f707d84SJiri Olsa 
12290b8891a8SHe Kuang static int config_term_pmu(struct perf_event_attr *attr,
12300b8891a8SHe Kuang 			   struct parse_events_term *term,
12310b8891a8SHe Kuang 			   struct parse_events_error *err)
12320b8891a8SHe Kuang {
12336fd1e519SIan Rogers 	if (term->type_term == PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE) {
12346fd1e519SIan Rogers 		const struct perf_pmu *pmu = perf_pmu__find_by_type(attr->type);
12356fd1e519SIan Rogers 
12366fd1e519SIan Rogers 		if (perf_pmu__supports_legacy_cache(pmu)) {
12376fd1e519SIan Rogers 			attr->type = PERF_TYPE_HW_CACHE;
12386fd1e519SIan Rogers 			return parse_events__decode_legacy_cache(term->config, pmu->type,
12396fd1e519SIan Rogers 								 &attr->config);
12406fd1e519SIan Rogers 		} else
12416fd1e519SIan Rogers 			term->type_term = PARSE_EVENTS__TERM_TYPE_USER;
12426fd1e519SIan Rogers 	}
12435ea8f2ccSIan Rogers 	if (term->type_term == PARSE_EVENTS__TERM_TYPE_HARDWARE) {
12445ea8f2ccSIan Rogers 		const struct perf_pmu *pmu = perf_pmu__find_by_type(attr->type);
12455ea8f2ccSIan Rogers 
12465ea8f2ccSIan Rogers 		if (!pmu) {
12475ea8f2ccSIan Rogers 			pr_debug("Failed to find PMU for type %d", attr->type);
12485ea8f2ccSIan Rogers 			return -EINVAL;
12495ea8f2ccSIan Rogers 		}
12505ea8f2ccSIan Rogers 		attr->type = PERF_TYPE_HARDWARE;
12515ea8f2ccSIan Rogers 		attr->config = ((__u64)pmu->type << PERF_PMU_TYPE_SHIFT) | term->val.num;
12525ea8f2ccSIan Rogers 		return 0;
12535ea8f2ccSIan Rogers 	}
1254dd60fba7SMathieu Poirier 	if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER ||
12556fd1e519SIan Rogers 	    term->type_term == PARSE_EVENTS__TERM_TYPE_DRV_CFG) {
12560b8891a8SHe Kuang 		/*
12570b8891a8SHe Kuang 		 * Always succeed for sysfs terms, as we dont know
12580b8891a8SHe Kuang 		 * at this point what type they need to have.
12590b8891a8SHe Kuang 		 */
12600b8891a8SHe Kuang 		return 0;
12616fd1e519SIan Rogers 	}
12620b8891a8SHe Kuang 	return config_term_common(attr, term, err);
12630b8891a8SHe Kuang }
12640b8891a8SHe Kuang 
1265378ef0f5SIan Rogers #ifdef HAVE_LIBTRACEEVENT
1266e637d177SHe Kuang static int config_term_tracepoint(struct perf_event_attr *attr,
1267e637d177SHe Kuang 				  struct parse_events_term *term,
1268e637d177SHe Kuang 				  struct parse_events_error *err)
1269e637d177SHe Kuang {
1270e637d177SHe Kuang 	switch (term->type_term) {
1271e637d177SHe Kuang 	case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
1272e637d177SHe Kuang 	case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
1273374ce938SWang Nan 	case PARSE_EVENTS__TERM_TYPE_INHERIT:
1274374ce938SWang Nan 	case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
1275792d48b4SArnaldo Carvalho de Melo 	case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
12762fda5adaSArnaldo Carvalho de Melo 	case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS:
1277626a6b78SWang Nan 	case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
1278626a6b78SWang Nan 	case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE:
12791b992154SAdrian Hunter 	case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT:
1280eb7a52d4SAdrian Hunter 	case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE:
1281e637d177SHe Kuang 		return config_term_common(attr, term, err);
1282e637d177SHe Kuang 	default:
1283e637d177SHe Kuang 		if (err) {
12846c191289SIan Rogers 			parse_events_error__handle(err, term->err_term,
1285448d732cSIan Rogers 				strdup("unknown term"),
1286448d732cSIan Rogers 				strdup("valid terms: call-graph,stack-size\n"));
1287e637d177SHe Kuang 		}
1288e637d177SHe Kuang 		return -EINVAL;
1289e637d177SHe Kuang 	}
1290e637d177SHe Kuang 
1291e637d177SHe Kuang 	return 0;
1292e637d177SHe Kuang }
1293378ef0f5SIan Rogers #endif
1294e637d177SHe Kuang 
12958f707d84SJiri Olsa static int config_attr(struct perf_event_attr *attr,
12963b0e371cSJiri Olsa 		       struct list_head *head,
12970b8891a8SHe Kuang 		       struct parse_events_error *err,
12980b8891a8SHe Kuang 		       config_term_func_t config_term)
12998f707d84SJiri Olsa {
13006cee6cd3SArnaldo Carvalho de Melo 	struct parse_events_term *term;
13018f707d84SJiri Olsa 
13028f707d84SJiri Olsa 	list_for_each_entry(term, head, list)
13033b0e371cSJiri Olsa 		if (config_term(attr, term, err))
13048f707d84SJiri Olsa 			return -EINVAL;
13058f707d84SJiri Olsa 
13068f707d84SJiri Olsa 	return 0;
13078f707d84SJiri Olsa }
13088f707d84SJiri Olsa 
1309930a2e29SJiri Olsa static int get_config_terms(struct list_head *head_config,
1310930a2e29SJiri Olsa 			    struct list_head *head_terms __maybe_unused)
1311930a2e29SJiri Olsa {
131205e54e23SIan Rogers #define ADD_CONFIG_TERM(__type, __weak)				\
131335ac0cadSArnaldo Carvalho de Melo 	struct evsel_config_term *__t;			\
1314930a2e29SJiri Olsa 								\
1315930a2e29SJiri Olsa 	__t = zalloc(sizeof(*__t));				\
1316930a2e29SJiri Olsa 	if (!__t)						\
1317930a2e29SJiri Olsa 		return -ENOMEM;					\
1318930a2e29SJiri Olsa 								\
1319930a2e29SJiri Olsa 	INIT_LIST_HEAD(&__t->list);				\
132035ac0cadSArnaldo Carvalho de Melo 	__t->type       = EVSEL__CONFIG_TERM_ ## __type;	\
132105e54e23SIan Rogers 	__t->weak	= __weak;				\
1322e884602bSLeo Yan 	list_add_tail(&__t->list, head_terms)
1323e884602bSLeo Yan 
132405e54e23SIan Rogers #define ADD_CONFIG_TERM_VAL(__type, __name, __val, __weak)	\
1325e884602bSLeo Yan do {								\
132605e54e23SIan Rogers 	ADD_CONFIG_TERM(__type, __weak);			\
1327e884602bSLeo Yan 	__t->val.__name = __val;				\
1328e884602bSLeo Yan } while (0)
1329e884602bSLeo Yan 
133005e54e23SIan Rogers #define ADD_CONFIG_TERM_STR(__type, __val, __weak)		\
1331e884602bSLeo Yan do {								\
133205e54e23SIan Rogers 	ADD_CONFIG_TERM(__type, __weak);			\
13333220fb8dSLeo Yan 	__t->val.str = strdup(__val);				\
13343220fb8dSLeo Yan 	if (!__t->val.str) {					\
13353220fb8dSLeo Yan 		zfree(&__t);					\
13363220fb8dSLeo Yan 		return -ENOMEM;					\
13373220fb8dSLeo Yan 	}							\
13383220fb8dSLeo Yan 	__t->free_str = true;					\
1339930a2e29SJiri Olsa } while (0)
1340930a2e29SJiri Olsa 
1341930a2e29SJiri Olsa 	struct parse_events_term *term;
1342930a2e29SJiri Olsa 
1343930a2e29SJiri Olsa 	list_for_each_entry(term, head_config, list) {
1344930a2e29SJiri Olsa 		switch (term->type_term) {
1345ee4c7588SJiri Olsa 		case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
134605e54e23SIan Rogers 			ADD_CONFIG_TERM_VAL(PERIOD, period, term->val.num, term->weak);
134732067712SKan Liang 			break;
134809af2a55SNamhyung Kim 		case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ:
134905e54e23SIan Rogers 			ADD_CONFIG_TERM_VAL(FREQ, freq, term->val.num, term->weak);
135009af2a55SNamhyung Kim 			break;
135132067712SKan Liang 		case PARSE_EVENTS__TERM_TYPE_TIME:
135205e54e23SIan Rogers 			ADD_CONFIG_TERM_VAL(TIME, time, term->val.num, term->weak);
135332067712SKan Liang 			break;
1354d457c963SKan Liang 		case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
135505e54e23SIan Rogers 			ADD_CONFIG_TERM_STR(CALLGRAPH, term->val.str, term->weak);
1356d457c963SKan Liang 			break;
1357ac12f676SAndi Kleen 		case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE:
135805e54e23SIan Rogers 			ADD_CONFIG_TERM_STR(BRANCH, term->val.str, term->weak);
1359ac12f676SAndi Kleen 			break;
1360d457c963SKan Liang 		case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
1361e884602bSLeo Yan 			ADD_CONFIG_TERM_VAL(STACK_USER, stack_user,
136205e54e23SIan Rogers 					    term->val.num, term->weak);
1363d457c963SKan Liang 			break;
1364374ce938SWang Nan 		case PARSE_EVENTS__TERM_TYPE_INHERIT:
1365e884602bSLeo Yan 			ADD_CONFIG_TERM_VAL(INHERIT, inherit,
136605e54e23SIan Rogers 					    term->val.num ? 1 : 0, term->weak);
1367374ce938SWang Nan 			break;
1368374ce938SWang Nan 		case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
1369e884602bSLeo Yan 			ADD_CONFIG_TERM_VAL(INHERIT, inherit,
137005e54e23SIan Rogers 					    term->val.num ? 0 : 1, term->weak);
1371374ce938SWang Nan 			break;
1372792d48b4SArnaldo Carvalho de Melo 		case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
1373e884602bSLeo Yan 			ADD_CONFIG_TERM_VAL(MAX_STACK, max_stack,
137405e54e23SIan Rogers 					    term->val.num, term->weak);
1375792d48b4SArnaldo Carvalho de Melo 			break;
13762fda5adaSArnaldo Carvalho de Melo 		case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS:
1377e884602bSLeo Yan 			ADD_CONFIG_TERM_VAL(MAX_EVENTS, max_events,
137805e54e23SIan Rogers 					    term->val.num, term->weak);
13792fda5adaSArnaldo Carvalho de Melo 			break;
1380626a6b78SWang Nan 		case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
1381e884602bSLeo Yan 			ADD_CONFIG_TERM_VAL(OVERWRITE, overwrite,
138205e54e23SIan Rogers 					    term->val.num ? 1 : 0, term->weak);
1383626a6b78SWang Nan 			break;
1384626a6b78SWang Nan 		case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE:
1385e884602bSLeo Yan 			ADD_CONFIG_TERM_VAL(OVERWRITE, overwrite,
138605e54e23SIan Rogers 					    term->val.num ? 0 : 1, term->weak);
1387626a6b78SWang Nan 			break;
1388dd60fba7SMathieu Poirier 		case PARSE_EVENTS__TERM_TYPE_DRV_CFG:
138905e54e23SIan Rogers 			ADD_CONFIG_TERM_STR(DRV_CFG, term->val.str, term->weak);
1390dd60fba7SMathieu Poirier 			break;
1391064b4e82SJin Yao 		case PARSE_EVENTS__TERM_TYPE_PERCORE:
1392e884602bSLeo Yan 			ADD_CONFIG_TERM_VAL(PERCORE, percore,
139305e54e23SIan Rogers 					    term->val.num ? true : false, term->weak);
1394064b4e82SJin Yao 			break;
13951b992154SAdrian Hunter 		case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT:
1396e884602bSLeo Yan 			ADD_CONFIG_TERM_VAL(AUX_OUTPUT, aux_output,
139705e54e23SIan Rogers 					    term->val.num ? 1 : 0, term->weak);
13981b992154SAdrian Hunter 			break;
1399eb7a52d4SAdrian Hunter 		case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE:
1400e884602bSLeo Yan 			ADD_CONFIG_TERM_VAL(AUX_SAMPLE_SIZE, aux_sample_size,
140105e54e23SIan Rogers 					    term->val.num, term->weak);
1402eb7a52d4SAdrian Hunter 			break;
1403930a2e29SJiri Olsa 		default:
1404930a2e29SJiri Olsa 			break;
1405930a2e29SJiri Olsa 		}
1406930a2e29SJiri Olsa 	}
1407a1ac7de6SAdrian Hunter 	return 0;
1408a1ac7de6SAdrian Hunter }
1409a1ac7de6SAdrian Hunter 
1410a1ac7de6SAdrian Hunter /*
141135ac0cadSArnaldo Carvalho de Melo  * Add EVSEL__CONFIG_TERM_CFG_CHG where cfg_chg will have a bit set for
1412a1ac7de6SAdrian Hunter  * each bit of attr->config that the user has changed.
1413a1ac7de6SAdrian Hunter  */
1414a1ac7de6SAdrian Hunter static int get_config_chgs(struct perf_pmu *pmu, struct list_head *head_config,
1415a1ac7de6SAdrian Hunter 			   struct list_head *head_terms)
1416a1ac7de6SAdrian Hunter {
1417a1ac7de6SAdrian Hunter 	struct parse_events_term *term;
1418a1ac7de6SAdrian Hunter 	u64 bits = 0;
1419a1ac7de6SAdrian Hunter 	int type;
1420a1ac7de6SAdrian Hunter 
1421a1ac7de6SAdrian Hunter 	list_for_each_entry(term, head_config, list) {
1422a1ac7de6SAdrian Hunter 		switch (term->type_term) {
1423a1ac7de6SAdrian Hunter 		case PARSE_EVENTS__TERM_TYPE_USER:
1424a1ac7de6SAdrian Hunter 			type = perf_pmu__format_type(&pmu->format, term->config);
1425a1ac7de6SAdrian Hunter 			if (type != PERF_PMU_FORMAT_VALUE_CONFIG)
1426a1ac7de6SAdrian Hunter 				continue;
1427a1ac7de6SAdrian Hunter 			bits |= perf_pmu__format_bits(&pmu->format, term->config);
1428a1ac7de6SAdrian Hunter 			break;
1429a1ac7de6SAdrian Hunter 		case PARSE_EVENTS__TERM_TYPE_CONFIG:
1430a1ac7de6SAdrian Hunter 			bits = ~(u64)0;
1431a1ac7de6SAdrian Hunter 			break;
1432a1ac7de6SAdrian Hunter 		default:
1433a1ac7de6SAdrian Hunter 			break;
1434a1ac7de6SAdrian Hunter 		}
1435a1ac7de6SAdrian Hunter 	}
1436a1ac7de6SAdrian Hunter 
1437a1ac7de6SAdrian Hunter 	if (bits)
143805e54e23SIan Rogers 		ADD_CONFIG_TERM_VAL(CFG_CHG, cfg_chg, bits, false);
1439a1ac7de6SAdrian Hunter 
1440a1ac7de6SAdrian Hunter #undef ADD_CONFIG_TERM
1441930a2e29SJiri Olsa 	return 0;
1442930a2e29SJiri Olsa }
1443930a2e29SJiri Olsa 
1444e637d177SHe Kuang int parse_events_add_tracepoint(struct list_head *list, int *idx,
14458c619d6aSWang Nan 				const char *sys, const char *event,
1446272ed29aSJiri Olsa 				struct parse_events_error *err,
1447e637d177SHe Kuang 				struct list_head *head_config)
1448e637d177SHe Kuang {
1449378ef0f5SIan Rogers #ifdef HAVE_LIBTRACEEVENT
1450e637d177SHe Kuang 	if (head_config) {
1451e637d177SHe Kuang 		struct perf_event_attr attr;
1452e637d177SHe Kuang 
1453272ed29aSJiri Olsa 		if (config_attr(&attr, head_config, err,
1454e637d177SHe Kuang 				config_term_tracepoint))
1455e637d177SHe Kuang 			return -EINVAL;
1456e637d177SHe Kuang 	}
1457e637d177SHe Kuang 
1458e637d177SHe Kuang 	if (strpbrk(sys, "*?"))
1459e637d177SHe Kuang 		return add_tracepoint_multi_sys(list, idx, sys, event,
1460272ed29aSJiri Olsa 						err, head_config);
1461e637d177SHe Kuang 	else
1462e637d177SHe Kuang 		return add_tracepoint_event(list, idx, sys, event,
1463272ed29aSJiri Olsa 					    err, head_config);
1464378ef0f5SIan Rogers #else
1465378ef0f5SIan Rogers 	(void)list;
1466378ef0f5SIan Rogers 	(void)idx;
1467378ef0f5SIan Rogers 	(void)sys;
1468378ef0f5SIan Rogers 	(void)event;
1469378ef0f5SIan Rogers 	(void)head_config;
1470378ef0f5SIan Rogers 	parse_events_error__handle(err, 0, strdup("unsupported tracepoint"),
1471378ef0f5SIan Rogers 				strdup("libtraceevent is necessary for tracepoint support"));
1472378ef0f5SIan Rogers 	return -1;
1473378ef0f5SIan Rogers #endif
1474e637d177SHe Kuang }
1475e637d177SHe Kuang 
14768bc75f69SIan Rogers static int __parse_events_add_numeric(struct parse_events_state *parse_state,
147787d650beSJiri Olsa 				struct list_head *list,
14788bc75f69SIan Rogers 				struct perf_pmu *pmu, u32 type, u64 config,
14798f707d84SJiri Olsa 				struct list_head *head_config)
148074d5b588SJaswinder Singh Rajput {
148189812fc8SJiri Olsa 	struct perf_event_attr attr;
1482930a2e29SJiri Olsa 	LIST_HEAD(config_terms);
14832b62b3a6SIan Rogers 	const char *name, *metric_id;
14849cbfa2f6SJin Yao 	int ret;
148574d5b588SJaswinder Singh Rajput 
148689812fc8SJiri Olsa 	memset(&attr, 0, sizeof(attr));
148789812fc8SJiri Olsa 	attr.type = type;
148889812fc8SJiri Olsa 	attr.config = config;
14898f707d84SJiri Olsa 
1490930a2e29SJiri Olsa 	if (head_config) {
14915d9cdc11SArnaldo Carvalho de Melo 		if (config_attr(&attr, head_config, parse_state->error,
14920b8891a8SHe Kuang 				config_term_common))
14938f707d84SJiri Olsa 			return -EINVAL;
14948f707d84SJiri Olsa 
1495930a2e29SJiri Olsa 		if (get_config_terms(head_config, &config_terms))
1496930a2e29SJiri Olsa 			return -ENOMEM;
1497930a2e29SJiri Olsa 	}
1498930a2e29SJiri Olsa 
14992b62b3a6SIan Rogers 	name = get_config_name(head_config);
15002b62b3a6SIan Rogers 	metric_id = get_config_metric_id(head_config);
15018bc75f69SIan Rogers 	ret = __add_event(list, &parse_state->idx, &attr, /*init_attr*/true, name,
15028bc75f69SIan Rogers 			metric_id, pmu, &config_terms, /*auto_merge_stats=*/false,
15038bc75f69SIan Rogers 			/*cpu_list=*/NULL) ? 0 : -ENOMEM;
150499fc5941SAdrian Hunter 	free_config_terms(&config_terms);
150599fc5941SAdrian Hunter 	return ret;
1506b908debdSIngo Molnar }
1507b908debdSIngo Molnar 
15088bc75f69SIan Rogers int parse_events_add_numeric(struct parse_events_state *parse_state,
15098bc75f69SIan Rogers 			     struct list_head *list,
15108bc75f69SIan Rogers 			     u32 type, u64 config,
15118bc75f69SIan Rogers 			     struct list_head *head_config,
15128bc75f69SIan Rogers 			     bool wildcard)
15138bc75f69SIan Rogers {
15148bc75f69SIan Rogers 	struct perf_pmu *pmu = NULL;
15158bc75f69SIan Rogers 	bool found_supported = false;
15168bc75f69SIan Rogers 
15178bc75f69SIan Rogers 	if (!wildcard)
15188bc75f69SIan Rogers 		return __parse_events_add_numeric(parse_state, list, /*pmu=*/NULL,
15198bc75f69SIan Rogers 						  type, config, head_config);
15208bc75f69SIan Rogers 
15218bc75f69SIan Rogers 	while ((pmu = perf_pmu__scan(pmu)) != NULL) {
15228bc75f69SIan Rogers 		int ret;
15238bc75f69SIan Rogers 
15248bc75f69SIan Rogers 		if (!perf_pmu__supports_wildcard_numeric(pmu))
15258bc75f69SIan Rogers 			continue;
15268bc75f69SIan Rogers 
1527411ad22eSIan Rogers 		if (parse_events__filter_pmu(parse_state, pmu))
1528411ad22eSIan Rogers 			continue;
1529411ad22eSIan Rogers 
15308bc75f69SIan Rogers 		found_supported = true;
15318bc75f69SIan Rogers 		ret = __parse_events_add_numeric(parse_state, list, pmu, pmu->type,
15328bc75f69SIan Rogers 						 config, head_config);
15338bc75f69SIan Rogers 		if (ret)
15348bc75f69SIan Rogers 			return ret;
15358bc75f69SIan Rogers 	}
15368bc75f69SIan Rogers 	return found_supported ? 0 : -EINVAL;
15378bc75f69SIan Rogers }
15388bc75f69SIan Rogers 
1539f0fbb114SAndi Kleen int parse_events_add_tool(struct parse_events_state *parse_state,
1540f0fbb114SAndi Kleen 			  struct list_head *list,
15418228e936SIan Rogers 			  int tool_event)
1542f0fbb114SAndi Kleen {
1543f0fbb114SAndi Kleen 	return add_event_tool(list, &parse_state->idx, tool_event);
1544f0fbb114SAndi Kleen }
1545f0fbb114SAndi Kleen 
1546064b4e82SJin Yao static bool config_term_percore(struct list_head *config_terms)
1547064b4e82SJin Yao {
154835ac0cadSArnaldo Carvalho de Melo 	struct evsel_config_term *term;
1549064b4e82SJin Yao 
1550064b4e82SJin Yao 	list_for_each_entry(term, config_terms, list) {
155135ac0cadSArnaldo Carvalho de Melo 		if (term->type == EVSEL__CONFIG_TERM_PERCORE)
1552064b4e82SJin Yao 			return term->val.percore;
1553064b4e82SJin Yao 	}
1554064b4e82SJin Yao 
1555064b4e82SJin Yao 	return false;
1556064b4e82SJin Yao }
1557064b4e82SJin Yao 
1558c199c11dSAgustin Vega-Frias int parse_events_add_pmu(struct parse_events_state *parse_state,
155936adec85SJiri Olsa 			 struct list_head *list, char *name,
15603cdc5c2cSKan Liang 			 struct list_head *head_config,
1561e733f87eSIan Rogers 			 bool auto_merge_stats)
15625f537a26SJiri Olsa {
15635f537a26SJiri Olsa 	struct perf_event_attr attr;
156446441bdcSMatt Fleming 	struct perf_pmu_info info;
15655f537a26SJiri Olsa 	struct perf_pmu *pmu;
156632dcd021SJiri Olsa 	struct evsel *evsel;
1567333b5665SAndi Kleen 	struct parse_events_error *err = parse_state->error;
1568930a2e29SJiri Olsa 	LIST_HEAD(config_terms);
15695f537a26SJiri Olsa 
1570f034fc50SAdrian Hunter 	pmu = parse_state->fake_pmu ?: perf_pmu__find(name);
1571f034fc50SAdrian Hunter 
1572f034fc50SAdrian Hunter 	if (verbose > 1 && !(pmu && pmu->selectable)) {
15734ac22b48SIan Rogers 		fprintf(stderr, "Attempting to add event pmu '%s' with '",
15744ac22b48SIan Rogers 			name);
15754ac22b48SIan Rogers 		if (head_config) {
15764ac22b48SIan Rogers 			struct parse_events_term *term;
15774ac22b48SIan Rogers 
15784ac22b48SIan Rogers 			list_for_each_entry(term, head_config, list) {
15794ac22b48SIan Rogers 				fprintf(stderr, "%s,", term->config);
15804ac22b48SIan Rogers 			}
15814ac22b48SIan Rogers 		}
15824ac22b48SIan Rogers 		fprintf(stderr, "' that may result in non-fatal errors\n");
15834ac22b48SIan Rogers 	}
15844ac22b48SIan Rogers 
1585333b5665SAndi Kleen 	if (!pmu) {
1586448d732cSIan Rogers 		char *err_str;
1587448d732cSIan Rogers 
1588448d732cSIan Rogers 		if (asprintf(&err_str,
1589333b5665SAndi Kleen 				"Cannot find PMU `%s'. Missing kernel support?",
1590448d732cSIan Rogers 				name) >= 0)
15916c191289SIan Rogers 			parse_events_error__handle(err, 0, err_str, NULL);
15925f537a26SJiri Olsa 		return -EINVAL;
1593333b5665SAndi Kleen 	}
159470c90e4aSIan Rogers 	if (head_config)
159570c90e4aSIan Rogers 		fix_raw(head_config, pmu);
15965f537a26SJiri Olsa 
1597dc0a6202SAdrian Hunter 	if (pmu->default_config) {
1598dc0a6202SAdrian Hunter 		memcpy(&attr, pmu->default_config,
1599dc0a6202SAdrian Hunter 		       sizeof(struct perf_event_attr));
1600dc0a6202SAdrian Hunter 	} else {
16015f537a26SJiri Olsa 		memset(&attr, 0, sizeof(attr));
1602dc0a6202SAdrian Hunter 	}
1603c9aeb2e9SIan Rogers 	attr.type = pmu->type;
16045f537a26SJiri Olsa 
1605ad962273SAdrian Hunter 	if (!head_config) {
16062b62b3a6SIan Rogers 		evsel = __add_event(list, &parse_state->idx, &attr,
16072b62b3a6SIan Rogers 				    /*init_attr=*/true, /*name=*/NULL,
16082b62b3a6SIan Rogers 				    /*metric_id=*/NULL, pmu,
16092b62b3a6SIan Rogers 				    /*config_terms=*/NULL, auto_merge_stats,
16102b62b3a6SIan Rogers 				    /*cpu_list=*/NULL);
1611cae256aeSIan Rogers 		return evsel ? 0 : -ENOMEM;
1612ad962273SAdrian Hunter 	}
1613ad962273SAdrian Hunter 
1614387ad33fSJiri Olsa 	if (!parse_state->fake_pmu && perf_pmu__check_alias(pmu, head_config, &info))
1615a6146d50SZheng Yan 		return -EINVAL;
1616a6146d50SZheng Yan 
16174ac22b48SIan Rogers 	if (verbose > 1) {
16184ac22b48SIan Rogers 		fprintf(stderr, "After aliases, add event pmu '%s' with '",
16194ac22b48SIan Rogers 			name);
16204ac22b48SIan Rogers 		if (head_config) {
16214ac22b48SIan Rogers 			struct parse_events_term *term;
16224ac22b48SIan Rogers 
16234ac22b48SIan Rogers 			list_for_each_entry(term, head_config, list) {
16244ac22b48SIan Rogers 				fprintf(stderr, "%s,", term->config);
16254ac22b48SIan Rogers 			}
16264ac22b48SIan Rogers 		}
16274ac22b48SIan Rogers 		fprintf(stderr, "' that may result in non-fatal errors\n");
16284ac22b48SIan Rogers 	}
16294ac22b48SIan Rogers 
16305f537a26SJiri Olsa 	/*
16315f537a26SJiri Olsa 	 * Configure hardcoded terms first, no need to check
16325f537a26SJiri Olsa 	 * return value when called with fail == 0 ;)
16335f537a26SJiri Olsa 	 */
16345d9cdc11SArnaldo Carvalho de Melo 	if (config_attr(&attr, head_config, parse_state->error, config_term_pmu))
1635c056ba6aSJiri Olsa 		return -EINVAL;
16365f537a26SJiri Olsa 
1637930a2e29SJiri Olsa 	if (get_config_terms(head_config, &config_terms))
1638930a2e29SJiri Olsa 		return -ENOMEM;
1639930a2e29SJiri Olsa 
1640a1ac7de6SAdrian Hunter 	/*
1641a1ac7de6SAdrian Hunter 	 * When using default config, record which bits of attr->config were
1642a1ac7de6SAdrian Hunter 	 * changed by the user.
1643a1ac7de6SAdrian Hunter 	 */
1644a1ac7de6SAdrian Hunter 	if (pmu->default_config && get_config_chgs(pmu, head_config, &config_terms))
1645a1ac7de6SAdrian Hunter 		return -ENOMEM;
1646a1ac7de6SAdrian Hunter 
1647387ad33fSJiri Olsa 	if (!parse_state->fake_pmu && perf_pmu__config(pmu, &attr, head_config, parse_state->error)) {
1648a7d212fcSAdrian Hunter 		free_config_terms(&config_terms);
16495f537a26SJiri Olsa 		return -EINVAL;
165038f2c422SIan Rogers 	}
16515f537a26SJiri Olsa 
16522b62b3a6SIan Rogers 	evsel = __add_event(list, &parse_state->idx, &attr, /*init_attr=*/true,
16532b62b3a6SIan Rogers 			    get_config_name(head_config),
16542b62b3a6SIan Rogers 			    get_config_metric_id(head_config), pmu,
16552b62b3a6SIan Rogers 			    &config_terms, auto_merge_stats, /*cpu_list=*/NULL);
165633321a06SIan Rogers 	if (!evsel)
165733321a06SIan Rogers 		return -ENOMEM;
165833321a06SIan Rogers 
165912279429SJin Yao 	if (evsel->name)
166012279429SJin Yao 		evsel->use_config_name = true;
166112279429SJin Yao 
166233321a06SIan Rogers 	evsel->percore = config_term_percore(&evsel->config_terms);
166333321a06SIan Rogers 
166433321a06SIan Rogers 	if (parse_state->fake_pmu)
166533321a06SIan Rogers 		return 0;
166633321a06SIan Rogers 
1667b194c9cdSIan Rogers 	free((char *)evsel->unit);
1668b194c9cdSIan Rogers 	evsel->unit = strdup(info.unit);
166946441bdcSMatt Fleming 	evsel->scale = info.scale;
1670044330c1SMatt Fleming 	evsel->per_pkg = info.per_pkg;
16711d9e446bSJiri Olsa 	evsel->snapshot = info.snapshot;
167233321a06SIan Rogers 	return 0;
16735f537a26SJiri Olsa }
16745f537a26SJiri Olsa 
16755d9cdc11SArnaldo Carvalho de Melo int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
1676fb081153SIan Rogers 			       char *str, struct list_head *head,
1677fb081153SIan Rogers 			       struct list_head **listp)
16782073ad33SAndi Kleen {
16792073ad33SAndi Kleen 	struct parse_events_term *term;
1680fb081153SIan Rogers 	struct list_head *list = NULL;
168191c9923aSZhengjun Xing 	struct list_head *orig_head = NULL;
16822073ad33SAndi Kleen 	struct perf_pmu *pmu = NULL;
16832073ad33SAndi Kleen 	int ok = 0;
1684fb081153SIan Rogers 	char *config;
16852073ad33SAndi Kleen 
16862073ad33SAndi Kleen 	*listp = NULL;
1687fb081153SIan Rogers 
1688fb081153SIan Rogers 	if (!head) {
1689fb081153SIan Rogers 		head = malloc(sizeof(struct list_head));
1690fb081153SIan Rogers 		if (!head)
1691fb081153SIan Rogers 			goto out_err;
1692fb081153SIan Rogers 
1693fb081153SIan Rogers 		INIT_LIST_HEAD(head);
1694fb081153SIan Rogers 	}
1695fb081153SIan Rogers 	config = strdup(str);
1696fb081153SIan Rogers 	if (!config)
1697fb081153SIan Rogers 		goto out_err;
1698fb081153SIan Rogers 
1699fb081153SIan Rogers 	if (parse_events_term__num(&term,
1700fb081153SIan Rogers 				   PARSE_EVENTS__TERM_TYPE_USER,
170166c9598bSNamhyung Kim 				   config, 1, false, NULL,
1702fb081153SIan Rogers 					NULL) < 0) {
1703fb081153SIan Rogers 		free(config);
1704fb081153SIan Rogers 		goto out_err;
1705fb081153SIan Rogers 	}
1706fb081153SIan Rogers 	list_add_tail(&term->list, head);
1707fb081153SIan Rogers 
17082073ad33SAndi Kleen 	/* Add it for all PMUs that support the alias */
17092073ad33SAndi Kleen 	list = malloc(sizeof(struct list_head));
17102073ad33SAndi Kleen 	if (!list)
1711fb081153SIan Rogers 		goto out_err;
1712fb081153SIan Rogers 
17132073ad33SAndi Kleen 	INIT_LIST_HEAD(list);
1714fb081153SIan Rogers 
17152073ad33SAndi Kleen 	while ((pmu = perf_pmu__scan(pmu)) != NULL) {
17162073ad33SAndi Kleen 		struct perf_pmu_alias *alias;
17172073ad33SAndi Kleen 
1718411ad22eSIan Rogers 		if (parse_events__filter_pmu(parse_state, pmu))
1719411ad22eSIan Rogers 			continue;
1720411ad22eSIan Rogers 
17212073ad33SAndi Kleen 		list_for_each_entry(alias, &pmu->aliases, list) {
17222073ad33SAndi Kleen 			if (!strcasecmp(alias->name, str)) {
172391c9923aSZhengjun Xing 				parse_events_copy_term_list(head, &orig_head);
1724c199c11dSAgustin Vega-Frias 				if (!parse_events_add_pmu(parse_state, list,
172591c9923aSZhengjun Xing 							  pmu->name, orig_head,
1726e733f87eSIan Rogers 							  /*auto_merge_stats=*/true)) {
1727d4953f7eSIan Rogers 					pr_debug("%s -> %s/%s/\n", str,
17282073ad33SAndi Kleen 						 pmu->name, alias->str);
17292073ad33SAndi Kleen 					ok++;
17302073ad33SAndi Kleen 				}
173191c9923aSZhengjun Xing 				parse_events_terms__delete(orig_head);
1732fb081153SIan Rogers 			}
1733fb081153SIan Rogers 		}
1734fb081153SIan Rogers 	}
1735b4a7276cSJohn Garry 
1736b4a7276cSJohn Garry 	if (parse_state->fake_pmu) {
1737b4a7276cSJohn Garry 		if (!parse_events_add_pmu(parse_state, list, str, head,
1738e733f87eSIan Rogers 					  /*auto_merge_stats=*/true)) {
1739b4a7276cSJohn Garry 			pr_debug("%s -> %s/%s/\n", str, "fake_pmu", str);
1740b4a7276cSJohn Garry 			ok++;
1741b4a7276cSJohn Garry 		}
1742b4a7276cSJohn Garry 	}
1743b4a7276cSJohn Garry 
1744fb081153SIan Rogers out_err:
1745fb081153SIan Rogers 	if (ok)
1746fb081153SIan Rogers 		*listp = list;
1747fb081153SIan Rogers 	else
1748fb081153SIan Rogers 		free(list);
17492073ad33SAndi Kleen 
17502073ad33SAndi Kleen 	parse_events_terms__delete(head);
1751fb081153SIan Rogers 	return ok ? 0 : -1;
17522073ad33SAndi Kleen }
17532073ad33SAndi Kleen 
17546a4bb04cSJiri Olsa int parse_events__modifier_group(struct list_head *list,
17556a4bb04cSJiri Olsa 				 char *event_mod)
175689efb029SJiri Olsa {
17576a4bb04cSJiri Olsa 	return parse_events__modifier_event(list, event_mod, true);
17586a4bb04cSJiri Olsa }
17596a4bb04cSJiri Olsa 
1760347c2f0aSIan Rogers void parse_events__set_leader(char *name, struct list_head *list)
17616a4bb04cSJiri Olsa {
176232dcd021SJiri Olsa 	struct evsel *leader;
17636a4bb04cSJiri Olsa 
1764854f7363SWang Nan 	if (list_empty(list)) {
1765854f7363SWang Nan 		WARN_ONCE(true, "WARNING: failed to set leader: empty list");
1766854f7363SWang Nan 		return;
1767854f7363SWang Nan 	}
1768854f7363SWang Nan 
1769347c2f0aSIan Rogers 	leader = list_first_entry(list, struct evsel, core.node);
1770ecdcf630SIan Rogers 	__perf_evlist__set_leader(list, &leader->core);
17714bb311b2SIan Rogers 	leader->group_name = name;
177289efb029SJiri Olsa }
177389efb029SJiri Olsa 
1774c5cd8ac0SDavid Ahern /* list_event is assumed to point to malloc'ed memory */
17755d7be90eSJiri Olsa void parse_events_update_lists(struct list_head *list_event,
17765d7be90eSJiri Olsa 			       struct list_head *list_all)
17775d7be90eSJiri Olsa {
17785d7be90eSJiri Olsa 	/*
17795d7be90eSJiri Olsa 	 * Called for single event definition. Update the
178089efb029SJiri Olsa 	 * 'all event' list, and reinit the 'single event'
17815d7be90eSJiri Olsa 	 * list, for next event definition.
17825d7be90eSJiri Olsa 	 */
17835d7be90eSJiri Olsa 	list_splice_tail(list_event, list_all);
1784b847cbdcSJiri Olsa 	free(list_event);
17855d7be90eSJiri Olsa }
17865d7be90eSJiri Olsa 
1787f5b1135bSJiri Olsa struct event_modifier {
1788f5b1135bSJiri Olsa 	int eu;
1789f5b1135bSJiri Olsa 	int ek;
1790f5b1135bSJiri Olsa 	int eh;
1791f5b1135bSJiri Olsa 	int eH;
1792f5b1135bSJiri Olsa 	int eG;
1793a1e12da4SJiri Olsa 	int eI;
1794f5b1135bSJiri Olsa 	int precise;
17957f94af7aSJiri Olsa 	int precise_max;
1796f5b1135bSJiri Olsa 	int exclude_GH;
17973c176311SJiri Olsa 	int sample_read;
1798e9a7c414SMichael Ellerman 	int pinned;
17995a5dfe4bSAndi Kleen 	int weak;
18000997a266SAndi Kleen 	int exclusive;
180101bd8efcSSong Liu 	int bpf_counter;
1802f5b1135bSJiri Olsa };
180361c45981SPaul Mackerras 
1804f5b1135bSJiri Olsa static int get_event_modifier(struct event_modifier *mod, char *str,
180532dcd021SJiri Olsa 			       struct evsel *evsel)
1806f5b1135bSJiri Olsa {
18071fc632ceSJiri Olsa 	int eu = evsel ? evsel->core.attr.exclude_user : 0;
18081fc632ceSJiri Olsa 	int ek = evsel ? evsel->core.attr.exclude_kernel : 0;
18091fc632ceSJiri Olsa 	int eh = evsel ? evsel->core.attr.exclude_hv : 0;
18101fc632ceSJiri Olsa 	int eH = evsel ? evsel->core.attr.exclude_host : 0;
18111fc632ceSJiri Olsa 	int eG = evsel ? evsel->core.attr.exclude_guest : 0;
18121fc632ceSJiri Olsa 	int eI = evsel ? evsel->core.attr.exclude_idle : 0;
18131fc632ceSJiri Olsa 	int precise = evsel ? evsel->core.attr.precise_ip : 0;
18147f94af7aSJiri Olsa 	int precise_max = 0;
18153c176311SJiri Olsa 	int sample_read = 0;
18161fc632ceSJiri Olsa 	int pinned = evsel ? evsel->core.attr.pinned : 0;
18170997a266SAndi Kleen 	int exclusive = evsel ? evsel->core.attr.exclusive : 0;
1818f5b1135bSJiri Olsa 
1819f5b1135bSJiri Olsa 	int exclude = eu | ek | eh;
1820f5b1135bSJiri Olsa 	int exclude_GH = evsel ? evsel->exclude_GH : 0;
18215a5dfe4bSAndi Kleen 	int weak = 0;
182201bd8efcSSong Liu 	int bpf_counter = 0;
1823f5b1135bSJiri Olsa 
1824f5b1135bSJiri Olsa 	memset(mod, 0, sizeof(*mod));
1825ceb53fbfSIngo Molnar 
182661c45981SPaul Mackerras 	while (*str) {
1827ab608344SPeter Zijlstra 		if (*str == 'u') {
1828ab608344SPeter Zijlstra 			if (!exclude)
1829ab608344SPeter Zijlstra 				exclude = eu = ek = eh = 1;
1830943b69acSJin Yao 			if (!exclude_GH && !perf_guest)
1831943b69acSJin Yao 				eG = 1;
183261c45981SPaul Mackerras 			eu = 0;
1833ab608344SPeter Zijlstra 		} else if (*str == 'k') {
1834ab608344SPeter Zijlstra 			if (!exclude)
1835ab608344SPeter Zijlstra 				exclude = eu = ek = eh = 1;
183661c45981SPaul Mackerras 			ek = 0;
1837ab608344SPeter Zijlstra 		} else if (*str == 'h') {
1838ab608344SPeter Zijlstra 			if (!exclude)
1839ab608344SPeter Zijlstra 				exclude = eu = ek = eh = 1;
184061c45981SPaul Mackerras 			eh = 0;
184199320cc8SJoerg Roedel 		} else if (*str == 'G') {
184299320cc8SJoerg Roedel 			if (!exclude_GH)
184399320cc8SJoerg Roedel 				exclude_GH = eG = eH = 1;
184499320cc8SJoerg Roedel 			eG = 0;
184599320cc8SJoerg Roedel 		} else if (*str == 'H') {
184699320cc8SJoerg Roedel 			if (!exclude_GH)
184799320cc8SJoerg Roedel 				exclude_GH = eG = eH = 1;
184899320cc8SJoerg Roedel 			eH = 0;
1849a1e12da4SJiri Olsa 		} else if (*str == 'I') {
1850a1e12da4SJiri Olsa 			eI = 1;
1851ab608344SPeter Zijlstra 		} else if (*str == 'p') {
1852ab608344SPeter Zijlstra 			precise++;
18531342798cSDavid Ahern 			/* use of precise requires exclude_guest */
18541342798cSDavid Ahern 			if (!exclude_GH)
18551342798cSDavid Ahern 				eG = 1;
18567f94af7aSJiri Olsa 		} else if (*str == 'P') {
18577f94af7aSJiri Olsa 			precise_max = 1;
18583c176311SJiri Olsa 		} else if (*str == 'S') {
18593c176311SJiri Olsa 			sample_read = 1;
1860e9a7c414SMichael Ellerman 		} else if (*str == 'D') {
1861e9a7c414SMichael Ellerman 			pinned = 1;
18620997a266SAndi Kleen 		} else if (*str == 'e') {
18630997a266SAndi Kleen 			exclusive = 1;
18645a5dfe4bSAndi Kleen 		} else if (*str == 'W') {
18655a5dfe4bSAndi Kleen 			weak = 1;
186601bd8efcSSong Liu 		} else if (*str == 'b') {
186701bd8efcSSong Liu 			bpf_counter = 1;
1868ab608344SPeter Zijlstra 		} else
186961c45981SPaul Mackerras 			break;
1870ab608344SPeter Zijlstra 
187161c45981SPaul Mackerras 		++str;
187261c45981SPaul Mackerras 	}
187374d5b588SJaswinder Singh Rajput 
187486470930SIngo Molnar 	/*
187589812fc8SJiri Olsa 	 * precise ip:
187689812fc8SJiri Olsa 	 *
187789812fc8SJiri Olsa 	 *  0 - SAMPLE_IP can have arbitrary skid
187889812fc8SJiri Olsa 	 *  1 - SAMPLE_IP must have constant skid
187989812fc8SJiri Olsa 	 *  2 - SAMPLE_IP requested to have 0 skid
188089812fc8SJiri Olsa 	 *  3 - SAMPLE_IP must have 0 skid
188189812fc8SJiri Olsa 	 *
188289812fc8SJiri Olsa 	 *  See also PERF_RECORD_MISC_EXACT_IP
188386470930SIngo Molnar 	 */
188489812fc8SJiri Olsa 	if (precise > 3)
188589812fc8SJiri Olsa 		return -EINVAL;
188686470930SIngo Molnar 
1887f5b1135bSJiri Olsa 	mod->eu = eu;
1888f5b1135bSJiri Olsa 	mod->ek = ek;
1889f5b1135bSJiri Olsa 	mod->eh = eh;
1890f5b1135bSJiri Olsa 	mod->eH = eH;
1891f5b1135bSJiri Olsa 	mod->eG = eG;
1892a1e12da4SJiri Olsa 	mod->eI = eI;
1893f5b1135bSJiri Olsa 	mod->precise = precise;
18947f94af7aSJiri Olsa 	mod->precise_max = precise_max;
1895f5b1135bSJiri Olsa 	mod->exclude_GH = exclude_GH;
18963c176311SJiri Olsa 	mod->sample_read = sample_read;
1897e9a7c414SMichael Ellerman 	mod->pinned = pinned;
18985a5dfe4bSAndi Kleen 	mod->weak = weak;
189901bd8efcSSong Liu 	mod->bpf_counter = bpf_counter;
19000997a266SAndi Kleen 	mod->exclusive = exclusive;
1901e9a7c414SMichael Ellerman 
1902f5b1135bSJiri Olsa 	return 0;
1903f5b1135bSJiri Olsa }
1904f5b1135bSJiri Olsa 
1905534123f4SJiri Olsa /*
1906534123f4SJiri Olsa  * Basic modifier sanity check to validate it contains only one
1907534123f4SJiri Olsa  * instance of any modifier (apart from 'p') present.
1908534123f4SJiri Olsa  */
1909534123f4SJiri Olsa static int check_modifier(char *str)
1910534123f4SJiri Olsa {
1911534123f4SJiri Olsa 	char *p = str;
1912534123f4SJiri Olsa 
1913534123f4SJiri Olsa 	/* The sizeof includes 0 byte as well. */
191401bd8efcSSong Liu 	if (strlen(str) > (sizeof("ukhGHpppPSDIWeb") - 1))
1915534123f4SJiri Olsa 		return -1;
1916534123f4SJiri Olsa 
1917534123f4SJiri Olsa 	while (*p) {
1918534123f4SJiri Olsa 		if (*p != 'p' && strchr(p + 1, *p))
1919534123f4SJiri Olsa 			return -1;
1920534123f4SJiri Olsa 		p++;
1921534123f4SJiri Olsa 	}
1922534123f4SJiri Olsa 
1923534123f4SJiri Olsa 	return 0;
1924534123f4SJiri Olsa }
1925534123f4SJiri Olsa 
1926f5b1135bSJiri Olsa int parse_events__modifier_event(struct list_head *list, char *str, bool add)
1927f5b1135bSJiri Olsa {
192832dcd021SJiri Olsa 	struct evsel *evsel;
1929f5b1135bSJiri Olsa 	struct event_modifier mod;
1930f5b1135bSJiri Olsa 
1931f5b1135bSJiri Olsa 	if (str == NULL)
1932f5b1135bSJiri Olsa 		return 0;
1933f5b1135bSJiri Olsa 
1934534123f4SJiri Olsa 	if (check_modifier(str))
1935534123f4SJiri Olsa 		return -EINVAL;
1936534123f4SJiri Olsa 
1937f5b1135bSJiri Olsa 	if (!add && get_event_modifier(&mod, str, NULL))
1938f5b1135bSJiri Olsa 		return -EINVAL;
1939f5b1135bSJiri Olsa 
1940e5cadb93SArnaldo Carvalho de Melo 	__evlist__for_each_entry(list, evsel) {
1941f5b1135bSJiri Olsa 		if (add && get_event_modifier(&mod, str, evsel))
1942f5b1135bSJiri Olsa 			return -EINVAL;
1943f5b1135bSJiri Olsa 
19441fc632ceSJiri Olsa 		evsel->core.attr.exclude_user   = mod.eu;
19451fc632ceSJiri Olsa 		evsel->core.attr.exclude_kernel = mod.ek;
19461fc632ceSJiri Olsa 		evsel->core.attr.exclude_hv     = mod.eh;
19471fc632ceSJiri Olsa 		evsel->core.attr.precise_ip     = mod.precise;
19481fc632ceSJiri Olsa 		evsel->core.attr.exclude_host   = mod.eH;
19491fc632ceSJiri Olsa 		evsel->core.attr.exclude_guest  = mod.eG;
19501fc632ceSJiri Olsa 		evsel->core.attr.exclude_idle   = mod.eI;
1951f5b1135bSJiri Olsa 		evsel->exclude_GH          = mod.exclude_GH;
19523c176311SJiri Olsa 		evsel->sample_read         = mod.sample_read;
19537f94af7aSJiri Olsa 		evsel->precise_max         = mod.precise_max;
19545a5dfe4bSAndi Kleen 		evsel->weak_group	   = mod.weak;
195501bd8efcSSong Liu 		evsel->bpf_counter	   = mod.bpf_counter;
1956e9a7c414SMichael Ellerman 
19570997a266SAndi Kleen 		if (evsel__is_group_leader(evsel)) {
19581fc632ceSJiri Olsa 			evsel->core.attr.pinned = mod.pinned;
19590997a266SAndi Kleen 			evsel->core.attr.exclusive = mod.exclusive;
19600997a266SAndi Kleen 		}
1961ceb53fbfSIngo Molnar 	}
196286470930SIngo Molnar 
196389812fc8SJiri Olsa 	return 0;
196486470930SIngo Molnar }
196586470930SIngo Molnar 
19668e8bbfb3SIan Rogers int parse_events_name(struct list_head *list, const char *name)
1967ac2ba9f3SRobert Richter {
196832dcd021SJiri Olsa 	struct evsel *evsel;
1969ac2ba9f3SRobert Richter 
1970e5cadb93SArnaldo Carvalho de Melo 	__evlist__for_each_entry(list, evsel) {
1971ac2ba9f3SRobert Richter 		if (!evsel->name)
1972ac2ba9f3SRobert Richter 			evsel->name = strdup(name);
1973ac2ba9f3SRobert Richter 	}
1974ac2ba9f3SRobert Richter 
1975ac2ba9f3SRobert Richter 	return 0;
1976ac2ba9f3SRobert Richter }
1977ac2ba9f3SRobert Richter 
19781244a327SJiri Olsa static int parse_events__scanner(const char *str,
19791244a327SJiri Olsa 				 struct parse_events_state *parse_state)
1980ac20de6fSZheng Yan {
1981ac20de6fSZheng Yan 	YY_BUFFER_STATE buffer;
1982ac20de6fSZheng Yan 	void *scanner;
1983ac20de6fSZheng Yan 	int ret;
1984ac20de6fSZheng Yan 
19851244a327SJiri Olsa 	ret = parse_events_lex_init_extra(parse_state, &scanner);
1986ac20de6fSZheng Yan 	if (ret)
1987ac20de6fSZheng Yan 		return ret;
1988ac20de6fSZheng Yan 
1989ac20de6fSZheng Yan 	buffer = parse_events__scan_string(str, scanner);
1990ac20de6fSZheng Yan 
1991ac20de6fSZheng Yan #ifdef PARSER_DEBUG
1992ac20de6fSZheng Yan 	parse_events_debug = 1;
1993ae762641SJiri Olsa 	parse_events_set_debug(1, scanner);
1994ac20de6fSZheng Yan #endif
19955d9cdc11SArnaldo Carvalho de Melo 	ret = parse_events_parse(parse_state, scanner);
1996ac20de6fSZheng Yan 
1997ac20de6fSZheng Yan 	parse_events__flush_buffer(buffer, scanner);
1998ac20de6fSZheng Yan 	parse_events__delete_buffer(buffer, scanner);
1999ac20de6fSZheng Yan 	parse_events_lex_destroy(scanner);
2000ac20de6fSZheng Yan 	return ret;
2001ac20de6fSZheng Yan }
2002ac20de6fSZheng Yan 
200390e2b22dSJiri Olsa /*
200490e2b22dSJiri Olsa  * parse event config string, return a list of event terms.
200590e2b22dSJiri Olsa  */
200690e2b22dSJiri Olsa int parse_events_terms(struct list_head *terms, const char *str)
200790e2b22dSJiri Olsa {
20085d9cdc11SArnaldo Carvalho de Melo 	struct parse_events_state parse_state = {
200990e2b22dSJiri Olsa 		.terms  = NULL,
20101244a327SJiri Olsa 		.stoken = PE_START_TERMS,
201190e2b22dSJiri Olsa 	};
201290e2b22dSJiri Olsa 	int ret;
201390e2b22dSJiri Olsa 
20141244a327SJiri Olsa 	ret = parse_events__scanner(str, &parse_state);
20154929e95aSJiri Olsa 
201690e2b22dSJiri Olsa 	if (!ret) {
20175d9cdc11SArnaldo Carvalho de Melo 		list_splice(parse_state.terms, terms);
20185d9cdc11SArnaldo Carvalho de Melo 		zfree(&parse_state.terms);
201990e2b22dSJiri Olsa 		return 0;
202090e2b22dSJiri Olsa 	}
202190e2b22dSJiri Olsa 
20225d9cdc11SArnaldo Carvalho de Melo 	parse_events_terms__delete(parse_state.terms);
202390e2b22dSJiri Olsa 	return ret;
202490e2b22dSJiri Olsa }
202590e2b22dSJiri Olsa 
2026347c2f0aSIan Rogers __weak int arch_evlist__cmp(const struct evsel *lhs, const struct evsel *rhs)
2027347c2f0aSIan Rogers {
2028347c2f0aSIan Rogers 	/* Order by insertion index. */
2029347c2f0aSIan Rogers 	return lhs->core.idx - rhs->core.idx;
2030347c2f0aSIan Rogers }
2031347c2f0aSIan Rogers 
2032347c2f0aSIan Rogers static int evlist__cmp(void *state, const struct list_head *l, const struct list_head *r)
2033347c2f0aSIan Rogers {
2034347c2f0aSIan Rogers 	const struct perf_evsel *lhs_core = container_of(l, struct perf_evsel, node);
2035347c2f0aSIan Rogers 	const struct evsel *lhs = container_of(lhs_core, struct evsel, core);
2036347c2f0aSIan Rogers 	const struct perf_evsel *rhs_core = container_of(r, struct perf_evsel, node);
2037347c2f0aSIan Rogers 	const struct evsel *rhs = container_of(rhs_core, struct evsel, core);
2038347c2f0aSIan Rogers 	int *leader_idx = state;
2039347c2f0aSIan Rogers 	int lhs_leader_idx = *leader_idx, rhs_leader_idx = *leader_idx, ret;
2040347c2f0aSIan Rogers 	const char *lhs_pmu_name, *rhs_pmu_name;
2041327daf34SIan Rogers 	bool lhs_has_group = false, rhs_has_group = false;
2042347c2f0aSIan Rogers 
2043347c2f0aSIan Rogers 	/*
2044347c2f0aSIan Rogers 	 * First sort by grouping/leader. Read the leader idx only if the evsel
2045347c2f0aSIan Rogers 	 * is part of a group, as -1 indicates no group.
2046347c2f0aSIan Rogers 	 */
2047327daf34SIan Rogers 	if (lhs_core->leader != lhs_core || lhs_core->nr_members > 1) {
2048327daf34SIan Rogers 		lhs_has_group = true;
2049347c2f0aSIan Rogers 		lhs_leader_idx = lhs_core->leader->idx;
2050327daf34SIan Rogers 	}
2051327daf34SIan Rogers 	if (rhs_core->leader != rhs_core || rhs_core->nr_members > 1) {
2052327daf34SIan Rogers 		rhs_has_group = true;
2053347c2f0aSIan Rogers 		rhs_leader_idx = rhs_core->leader->idx;
2054327daf34SIan Rogers 	}
2055347c2f0aSIan Rogers 
2056347c2f0aSIan Rogers 	if (lhs_leader_idx != rhs_leader_idx)
2057347c2f0aSIan Rogers 		return lhs_leader_idx - rhs_leader_idx;
2058347c2f0aSIan Rogers 
2059327daf34SIan Rogers 	/* Group by PMU if there is a group. Groups can't span PMUs. */
2060327daf34SIan Rogers 	if (lhs_has_group && rhs_has_group) {
2061347c2f0aSIan Rogers 		lhs_pmu_name = evsel__group_pmu_name(lhs);
2062347c2f0aSIan Rogers 		rhs_pmu_name = evsel__group_pmu_name(rhs);
2063347c2f0aSIan Rogers 		ret = strcmp(lhs_pmu_name, rhs_pmu_name);
2064347c2f0aSIan Rogers 		if (ret)
2065347c2f0aSIan Rogers 			return ret;
2066327daf34SIan Rogers 	}
2067347c2f0aSIan Rogers 
2068347c2f0aSIan Rogers 	/* Architecture specific sorting. */
2069347c2f0aSIan Rogers 	return arch_evlist__cmp(lhs, rhs);
2070347c2f0aSIan Rogers }
2071347c2f0aSIan Rogers 
2072a4c7d7c5SIan Rogers static bool parse_events__sort_events_and_fix_groups(struct list_head *list)
2073347c2f0aSIan Rogers {
2074a4c7d7c5SIan Rogers 	int idx = 0, unsorted_idx = -1;
2075347c2f0aSIan Rogers 	struct evsel *pos, *cur_leader = NULL;
2076347c2f0aSIan Rogers 	struct perf_evsel *cur_leaders_grp = NULL;
2077a4c7d7c5SIan Rogers 	bool idx_changed = false;
2078a4c7d7c5SIan Rogers 	int orig_num_leaders = 0, num_leaders = 0;
2079347c2f0aSIan Rogers 
2080347c2f0aSIan Rogers 	/*
2081347c2f0aSIan Rogers 	 * Compute index to insert ungrouped events at. Place them where the
2082347c2f0aSIan Rogers 	 * first ungrouped event appears.
2083347c2f0aSIan Rogers 	 */
2084347c2f0aSIan Rogers 	list_for_each_entry(pos, list, core.node) {
2085347c2f0aSIan Rogers 		const struct evsel *pos_leader = evsel__leader(pos);
2086347c2f0aSIan Rogers 
2087a4c7d7c5SIan Rogers 		if (pos == pos_leader)
2088a4c7d7c5SIan Rogers 			orig_num_leaders++;
2089347c2f0aSIan Rogers 
2090a4c7d7c5SIan Rogers 		/*
2091a4c7d7c5SIan Rogers 		 * Ensure indexes are sequential, in particular for multiple
2092a4c7d7c5SIan Rogers 		 * event lists being merged. The indexes are used to detect when
2093a4c7d7c5SIan Rogers 		 * the user order is modified.
2094a4c7d7c5SIan Rogers 		 */
2095a4c7d7c5SIan Rogers 		pos->core.idx = idx++;
2096a4c7d7c5SIan Rogers 
2097a4c7d7c5SIan Rogers 		if (unsorted_idx == -1 && pos == pos_leader && pos->core.nr_members < 2)
2098a4c7d7c5SIan Rogers 			unsorted_idx = pos->core.idx;
2099347c2f0aSIan Rogers 	}
2100347c2f0aSIan Rogers 
2101347c2f0aSIan Rogers 	/* Sort events. */
2102a4c7d7c5SIan Rogers 	list_sort(&unsorted_idx, list, evlist__cmp);
2103347c2f0aSIan Rogers 
2104347c2f0aSIan Rogers 	/*
2105347c2f0aSIan Rogers 	 * Recompute groups, splitting for PMUs and adding groups for events
2106347c2f0aSIan Rogers 	 * that require them.
2107347c2f0aSIan Rogers 	 */
2108347c2f0aSIan Rogers 	idx = 0;
2109347c2f0aSIan Rogers 	list_for_each_entry(pos, list, core.node) {
2110347c2f0aSIan Rogers 		const struct evsel *pos_leader = evsel__leader(pos);
2111347c2f0aSIan Rogers 		const char *pos_pmu_name = evsel__group_pmu_name(pos);
2112347c2f0aSIan Rogers 		const char *cur_leader_pmu_name, *pos_leader_pmu_name;
2113347c2f0aSIan Rogers 		bool force_grouped = arch_evsel__must_be_in_group(pos);
2114347c2f0aSIan Rogers 
2115347c2f0aSIan Rogers 		/* Reset index and nr_members. */
2116a4c7d7c5SIan Rogers 		if (pos->core.idx != idx)
2117a4c7d7c5SIan Rogers 			idx_changed = true;
2118347c2f0aSIan Rogers 		pos->core.idx = idx++;
2119347c2f0aSIan Rogers 		pos->core.nr_members = 0;
2120347c2f0aSIan Rogers 
2121347c2f0aSIan Rogers 		/*
2122347c2f0aSIan Rogers 		 * Set the group leader respecting the given groupings and that
2123347c2f0aSIan Rogers 		 * groups can't span PMUs.
2124347c2f0aSIan Rogers 		 */
2125347c2f0aSIan Rogers 		if (!cur_leader)
2126347c2f0aSIan Rogers 			cur_leader = pos;
2127347c2f0aSIan Rogers 
2128347c2f0aSIan Rogers 		cur_leader_pmu_name = evsel__group_pmu_name(cur_leader);
2129347c2f0aSIan Rogers 		if ((cur_leaders_grp != pos->core.leader && !force_grouped) ||
2130347c2f0aSIan Rogers 		    strcmp(cur_leader_pmu_name, pos_pmu_name)) {
2131347c2f0aSIan Rogers 			/* Event is for a different group/PMU than last. */
2132347c2f0aSIan Rogers 			cur_leader = pos;
2133347c2f0aSIan Rogers 			/*
2134347c2f0aSIan Rogers 			 * Remember the leader's group before it is overwritten,
2135347c2f0aSIan Rogers 			 * so that later events match as being in the same
2136347c2f0aSIan Rogers 			 * group.
2137347c2f0aSIan Rogers 			 */
2138347c2f0aSIan Rogers 			cur_leaders_grp = pos->core.leader;
2139347c2f0aSIan Rogers 		}
2140347c2f0aSIan Rogers 		pos_leader_pmu_name = evsel__group_pmu_name(pos_leader);
2141347c2f0aSIan Rogers 		if (strcmp(pos_leader_pmu_name, pos_pmu_name) || force_grouped) {
2142347c2f0aSIan Rogers 			/*
2143347c2f0aSIan Rogers 			 * Event's PMU differs from its leader's. Groups can't
2144347c2f0aSIan Rogers 			 * span PMUs, so update leader from the group/PMU
2145347c2f0aSIan Rogers 			 * tracker.
2146347c2f0aSIan Rogers 			 */
2147347c2f0aSIan Rogers 			evsel__set_leader(pos, cur_leader);
2148347c2f0aSIan Rogers 		}
2149347c2f0aSIan Rogers 	}
2150347c2f0aSIan Rogers 	list_for_each_entry(pos, list, core.node) {
2151a4c7d7c5SIan Rogers 		struct evsel *pos_leader = evsel__leader(pos);
2152a4c7d7c5SIan Rogers 
2153a4c7d7c5SIan Rogers 		if (pos == pos_leader)
2154a4c7d7c5SIan Rogers 			num_leaders++;
2155a4c7d7c5SIan Rogers 		pos_leader->core.nr_members++;
2156347c2f0aSIan Rogers 	}
2157a4c7d7c5SIan Rogers 	return idx_changed || num_leaders != orig_num_leaders;
2158347c2f0aSIan Rogers }
2159347c2f0aSIan Rogers 
2160411ad22eSIan Rogers int __parse_events(struct evlist *evlist, const char *str, const char *pmu_filter,
2161a4c7d7c5SIan Rogers 		   struct parse_events_error *err, struct perf_pmu *fake_pmu,
2162a4c7d7c5SIan Rogers 		   bool warn_if_reordered)
216386470930SIngo Molnar {
21645d9cdc11SArnaldo Carvalho de Melo 	struct parse_events_state parse_state = {
21655d9cdc11SArnaldo Carvalho de Melo 		.list	  = LIST_HEAD_INIT(parse_state.list),
21666484d2f9SJiri Olsa 		.idx	  = evlist->core.nr_entries,
2167b39b8393SJiri Olsa 		.error	  = err,
21687630b3e2SWang Nan 		.evlist	  = evlist,
21691244a327SJiri Olsa 		.stoken	  = PE_START_EVENTS,
21703bf91aa5SArnaldo Carvalho de Melo 		.fake_pmu = fake_pmu,
2171411ad22eSIan Rogers 		.pmu_filter = pmu_filter,
21726fd1e519SIan Rogers 		.match_legacy_cache_terms = true,
217346010ab2SJiri Olsa 	};
217446010ab2SJiri Olsa 	int ret;
217586470930SIngo Molnar 
21761244a327SJiri Olsa 	ret = parse_events__scanner(str, &parse_state);
217715bfd2ccSWang Nan 
21788e8714c3SIan Rogers 	if (!ret && list_empty(&parse_state.list)) {
2179c23080a6SArnaldo Carvalho de Melo 		WARN_ONCE(true, "WARNING: event parser found nothing\n");
2180854f7363SWang Nan 		return -1;
2181854f7363SWang Nan 	}
2182854f7363SWang Nan 
2183a4c7d7c5SIan Rogers 	if (parse_events__sort_events_and_fix_groups(&parse_state.list) &&
2184a4c7d7c5SIan Rogers 	    warn_if_reordered && !parse_state.wild_card_pmus)
2185a4c7d7c5SIan Rogers 		pr_warning("WARNING: events were regrouped to match PMUs\n");
2186347c2f0aSIan Rogers 
21878e8714c3SIan Rogers 	/*
21888e8714c3SIan Rogers 	 * Add list to the evlist even with errors to allow callers to clean up.
21898e8714c3SIan Rogers 	 */
2190e414fd1aSArnaldo Carvalho de Melo 	evlist__splice_list_tail(evlist, &parse_state.list);
21918e8714c3SIan Rogers 
21928e8714c3SIan Rogers 	if (!ret) {
21938e8714c3SIan Rogers 		struct evsel *last;
21948e8714c3SIan Rogers 
2195515dbe48SJiri Olsa 		last = evlist__last(evlist);
219615bfd2ccSWang Nan 		last->cmdline_group_boundary = true;
219715bfd2ccSWang Nan 
219886470930SIngo Molnar 		return 0;
219986470930SIngo Molnar 	}
220086470930SIngo Molnar 
22015d7be90eSJiri Olsa 	/*
22025d7be90eSJiri Olsa 	 * There are 2 users - builtin-record and builtin-test objects.
2203c12995a5SJiri Olsa 	 * Both call evlist__delete in case of error, so we dont
22045d7be90eSJiri Olsa 	 * need to bother.
22055d7be90eSJiri Olsa 	 */
220689812fc8SJiri Olsa 	return ret;
220789812fc8SJiri Olsa }
220889812fc8SJiri Olsa 
2209806731a9SAdrian Hunter int parse_event(struct evlist *evlist, const char *str)
2210806731a9SAdrian Hunter {
2211806731a9SAdrian Hunter 	struct parse_events_error err;
2212806731a9SAdrian Hunter 	int ret;
2213806731a9SAdrian Hunter 
2214806731a9SAdrian Hunter 	parse_events_error__init(&err);
2215806731a9SAdrian Hunter 	ret = parse_events(evlist, str, &err);
2216806731a9SAdrian Hunter 	parse_events_error__exit(&err);
2217806731a9SAdrian Hunter 	return ret;
2218806731a9SAdrian Hunter }
2219806731a9SAdrian Hunter 
222007eafd4eSIan Rogers void parse_events_error__init(struct parse_events_error *err)
222107eafd4eSIan Rogers {
222207eafd4eSIan Rogers 	bzero(err, sizeof(*err));
222307eafd4eSIan Rogers }
222407eafd4eSIan Rogers 
222507eafd4eSIan Rogers void parse_events_error__exit(struct parse_events_error *err)
222607eafd4eSIan Rogers {
222707eafd4eSIan Rogers 	zfree(&err->str);
222807eafd4eSIan Rogers 	zfree(&err->help);
222907eafd4eSIan Rogers 	zfree(&err->first_str);
223007eafd4eSIan Rogers 	zfree(&err->first_help);
223107eafd4eSIan Rogers }
223207eafd4eSIan Rogers 
22336c191289SIan Rogers void parse_events_error__handle(struct parse_events_error *err, int idx,
22346c191289SIan Rogers 				char *str, char *help)
22356c191289SIan Rogers {
2236806731a9SAdrian Hunter 	if (WARN(!str || !err, "WARNING: failed to provide error string or struct\n"))
22372e828582SAdrian Hunter 		goto out_free;
22386c191289SIan Rogers 	switch (err->num_errors) {
22396c191289SIan Rogers 	case 0:
22406c191289SIan Rogers 		err->idx = idx;
22416c191289SIan Rogers 		err->str = str;
22426c191289SIan Rogers 		err->help = help;
22436c191289SIan Rogers 		break;
22446c191289SIan Rogers 	case 1:
22456c191289SIan Rogers 		err->first_idx = err->idx;
22466c191289SIan Rogers 		err->idx = idx;
22476c191289SIan Rogers 		err->first_str = err->str;
22486c191289SIan Rogers 		err->str = str;
22496c191289SIan Rogers 		err->first_help = err->help;
22506c191289SIan Rogers 		err->help = help;
22516c191289SIan Rogers 		break;
22526c191289SIan Rogers 	default:
22536c191289SIan Rogers 		pr_debug("Multiple errors dropping message: %s (%s)\n",
22546c191289SIan Rogers 			err->str, err->help);
22556c191289SIan Rogers 		free(err->str);
22566c191289SIan Rogers 		err->str = str;
22576c191289SIan Rogers 		free(err->help);
22586c191289SIan Rogers 		err->help = help;
22596c191289SIan Rogers 		break;
22606c191289SIan Rogers 	}
22616c191289SIan Rogers 	err->num_errors++;
22622e828582SAdrian Hunter 	return;
22632e828582SAdrian Hunter 
22642e828582SAdrian Hunter out_free:
22652e828582SAdrian Hunter 	free(str);
22662e828582SAdrian Hunter 	free(help);
22676c191289SIan Rogers }
22686c191289SIan Rogers 
2269b39b8393SJiri Olsa #define MAX_WIDTH 1000
2270b39b8393SJiri Olsa static int get_term_width(void)
2271b39b8393SJiri Olsa {
2272b39b8393SJiri Olsa 	struct winsize ws;
2273b39b8393SJiri Olsa 
2274b39b8393SJiri Olsa 	get_term_dimensions(&ws);
2275b39b8393SJiri Olsa 	return ws.ws_col > MAX_WIDTH ? MAX_WIDTH : ws.ws_col;
2276b39b8393SJiri Olsa }
2277b39b8393SJiri Olsa 
22786c191289SIan Rogers static void __parse_events_error__print(int err_idx, const char *err_str,
2279a910e466SIan Rogers 					const char *err_help, const char *event)
2280b39b8393SJiri Olsa {
2281b39b8393SJiri Olsa 	const char *str = "invalid or unsupported event: ";
2282b39b8393SJiri Olsa 	char _buf[MAX_WIDTH];
2283b39b8393SJiri Olsa 	char *buf = (char *) event;
2284b39b8393SJiri Olsa 	int idx = 0;
2285a910e466SIan Rogers 	if (err_str) {
2286b39b8393SJiri Olsa 		/* -2 for extra '' in the final fprintf */
2287b39b8393SJiri Olsa 		int width       = get_term_width() - 2;
2288b39b8393SJiri Olsa 		int len_event   = strlen(event);
2289b39b8393SJiri Olsa 		int len_str, max_len, cut = 0;
2290b39b8393SJiri Olsa 
2291b39b8393SJiri Olsa 		/*
2292b39b8393SJiri Olsa 		 * Maximum error index indent, we will cut
2293b39b8393SJiri Olsa 		 * the event string if it's bigger.
2294b39b8393SJiri Olsa 		 */
2295141b2d31SAdrian Hunter 		int max_err_idx = 13;
2296b39b8393SJiri Olsa 
2297b39b8393SJiri Olsa 		/*
2298b39b8393SJiri Olsa 		 * Let's be specific with the message when
2299b39b8393SJiri Olsa 		 * we have the precise error.
2300b39b8393SJiri Olsa 		 */
2301b39b8393SJiri Olsa 		str     = "event syntax error: ";
2302b39b8393SJiri Olsa 		len_str = strlen(str);
2303b39b8393SJiri Olsa 		max_len = width - len_str;
2304b39b8393SJiri Olsa 
2305b39b8393SJiri Olsa 		buf = _buf;
2306b39b8393SJiri Olsa 
2307bd1a0be5SAdam Buchbinder 		/* We're cutting from the beginning. */
2308a910e466SIan Rogers 		if (err_idx > max_err_idx)
2309a910e466SIan Rogers 			cut = err_idx - max_err_idx;
2310b39b8393SJiri Olsa 
2311b39b8393SJiri Olsa 		strncpy(buf, event + cut, max_len);
2312b39b8393SJiri Olsa 
2313b39b8393SJiri Olsa 		/* Mark cut parts with '..' on both sides. */
2314b39b8393SJiri Olsa 		if (cut)
2315b39b8393SJiri Olsa 			buf[0] = buf[1] = '.';
2316b39b8393SJiri Olsa 
2317b39b8393SJiri Olsa 		if ((len_event - cut) > max_len) {
2318b39b8393SJiri Olsa 			buf[max_len - 1] = buf[max_len - 2] = '.';
2319b39b8393SJiri Olsa 			buf[max_len] = 0;
2320b39b8393SJiri Olsa 		}
2321b39b8393SJiri Olsa 
2322a910e466SIan Rogers 		idx = len_str + err_idx - cut;
2323b39b8393SJiri Olsa 	}
2324b39b8393SJiri Olsa 
2325b39b8393SJiri Olsa 	fprintf(stderr, "%s'%s'\n", str, buf);
2326b39b8393SJiri Olsa 	if (idx) {
2327a910e466SIan Rogers 		fprintf(stderr, "%*s\\___ %s\n", idx + 1, "", err_str);
2328a910e466SIan Rogers 		if (err_help)
2329a910e466SIan Rogers 			fprintf(stderr, "\n%s\n", err_help);
2330a910e466SIan Rogers 	}
2331a910e466SIan Rogers }
2332a910e466SIan Rogers 
23336c191289SIan Rogers void parse_events_error__print(struct parse_events_error *err,
2334a910e466SIan Rogers 			       const char *event)
2335a910e466SIan Rogers {
2336a910e466SIan Rogers 	if (!err->num_errors)
2337a910e466SIan Rogers 		return;
2338a910e466SIan Rogers 
23396c191289SIan Rogers 	__parse_events_error__print(err->idx, err->str, err->help, event);
2340a910e466SIan Rogers 
2341a910e466SIan Rogers 	if (err->num_errors > 1) {
2342a910e466SIan Rogers 		fputs("\nInitial error:\n", stderr);
23436c191289SIan Rogers 		__parse_events_error__print(err->first_idx, err->first_str,
2344a910e466SIan Rogers 					err->first_help, event);
2345b39b8393SJiri Olsa 	}
2346b39b8393SJiri Olsa }
2347b39b8393SJiri Olsa 
2348b39b8393SJiri Olsa #undef MAX_WIDTH
2349b39b8393SJiri Olsa 
2350f120f9d5SJiri Olsa int parse_events_option(const struct option *opt, const char *str,
23511d037ca1SIrina Tirdea 			int unset __maybe_unused)
2352f120f9d5SJiri Olsa {
2353411ad22eSIan Rogers 	struct parse_events_option_args *args = opt->value;
2354a910e466SIan Rogers 	struct parse_events_error err;
2355a910e466SIan Rogers 	int ret;
2356a910e466SIan Rogers 
235707eafd4eSIan Rogers 	parse_events_error__init(&err);
2358411ad22eSIan Rogers 	ret = __parse_events(*args->evlistp, str, args->pmu_filter, &err,
2359411ad22eSIan Rogers 			     /*fake_pmu=*/NULL, /*warn_if_reordered=*/true);
23609175ce1fSAndi Kleen 
2361333b5665SAndi Kleen 	if (ret) {
23626c191289SIan Rogers 		parse_events_error__print(&err, str);
2363333b5665SAndi Kleen 		fprintf(stderr, "Run 'perf list' for a list of valid events\n");
2364333b5665SAndi Kleen 	}
236507eafd4eSIan Rogers 	parse_events_error__exit(&err);
2366b39b8393SJiri Olsa 
23679175ce1fSAndi Kleen 	return ret;
2368f120f9d5SJiri Olsa }
2369f120f9d5SJiri Olsa 
2370d0abbc3cSArnaldo Carvalho de Melo int parse_events_option_new_evlist(const struct option *opt, const char *str, int unset)
2371d0abbc3cSArnaldo Carvalho de Melo {
2372411ad22eSIan Rogers 	struct parse_events_option_args *args = opt->value;
2373d0abbc3cSArnaldo Carvalho de Melo 	int ret;
2374d0abbc3cSArnaldo Carvalho de Melo 
2375411ad22eSIan Rogers 	if (*args->evlistp == NULL) {
2376411ad22eSIan Rogers 		*args->evlistp = evlist__new();
2377d0abbc3cSArnaldo Carvalho de Melo 
2378411ad22eSIan Rogers 		if (*args->evlistp == NULL) {
2379d0abbc3cSArnaldo Carvalho de Melo 			fprintf(stderr, "Not enough memory to create evlist\n");
2380d0abbc3cSArnaldo Carvalho de Melo 			return -1;
2381d0abbc3cSArnaldo Carvalho de Melo 		}
2382d0abbc3cSArnaldo Carvalho de Melo 	}
2383d0abbc3cSArnaldo Carvalho de Melo 	ret = parse_events_option(opt, str, unset);
2384d0abbc3cSArnaldo Carvalho de Melo 	if (ret) {
2385411ad22eSIan Rogers 		evlist__delete(*args->evlistp);
2386411ad22eSIan Rogers 		*args->evlistp = NULL;
2387d0abbc3cSArnaldo Carvalho de Melo 	}
2388d0abbc3cSArnaldo Carvalho de Melo 
2389d0abbc3cSArnaldo Carvalho de Melo 	return ret;
2390d0abbc3cSArnaldo Carvalho de Melo }
2391d0abbc3cSArnaldo Carvalho de Melo 
23924ba1faa1SWang Nan static int
239363503dbaSJiri Olsa foreach_evsel_in_last_glob(struct evlist *evlist,
239432dcd021SJiri Olsa 			   int (*func)(struct evsel *evsel,
23954ba1faa1SWang Nan 				       const void *arg),
23964ba1faa1SWang Nan 			   const void *arg)
2397c171b552SLi Zefan {
239832dcd021SJiri Olsa 	struct evsel *last = NULL;
23994ba1faa1SWang Nan 	int err;
2400c171b552SLi Zefan 
2401854f7363SWang Nan 	/*
2402854f7363SWang Nan 	 * Don't return when list_empty, give func a chance to report
2403854f7363SWang Nan 	 * error when it found last == NULL.
2404854f7363SWang Nan 	 *
2405854f7363SWang Nan 	 * So no need to WARN here, let *func do this.
2406854f7363SWang Nan 	 */
24076484d2f9SJiri Olsa 	if (evlist->core.nr_entries > 0)
2408515dbe48SJiri Olsa 		last = evlist__last(evlist);
240969aad6f1SArnaldo Carvalho de Melo 
241015bfd2ccSWang Nan 	do {
24114ba1faa1SWang Nan 		err = (*func)(last, arg);
24124ba1faa1SWang Nan 		if (err)
2413c171b552SLi Zefan 			return -1;
24144ba1faa1SWang Nan 		if (!last)
24154ba1faa1SWang Nan 			return 0;
2416c171b552SLi Zefan 
2417ce9036a6SJiri Olsa 		if (last->core.node.prev == &evlist->core.entries)
241815bfd2ccSWang Nan 			return 0;
2419b27c4eceSJiri Olsa 		last = list_entry(last->core.node.prev, struct evsel, core.node);
242015bfd2ccSWang Nan 	} while (!last->cmdline_group_boundary);
242115bfd2ccSWang Nan 
2422c171b552SLi Zefan 	return 0;
2423c171b552SLi Zefan }
2424c171b552SLi Zefan 
242532dcd021SJiri Olsa static int set_filter(struct evsel *evsel, const void *arg)
24264ba1faa1SWang Nan {
24274ba1faa1SWang Nan 	const char *str = arg;
24281e857484SMathieu Poirier 	bool found = false;
24291e857484SMathieu Poirier 	int nr_addr_filters = 0;
24301e857484SMathieu Poirier 	struct perf_pmu *pmu = NULL;
24314ba1faa1SWang Nan 
243249836f78SJack Henschel 	if (evsel == NULL) {
243349836f78SJack Henschel 		fprintf(stderr,
243449836f78SJack Henschel 			"--filter option should follow a -e tracepoint or HW tracer option\n");
243549836f78SJack Henschel 		return -1;
243649836f78SJack Henschel 	}
24374ba1faa1SWang Nan 
24381fc632ceSJiri Olsa 	if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT) {
2439ad681adfSArnaldo Carvalho de Melo 		if (evsel__append_tp_filter(evsel, str) < 0) {
24404ba1faa1SWang Nan 			fprintf(stderr,
24414ba1faa1SWang Nan 				"not enough memory to hold filter string\n");
24424ba1faa1SWang Nan 			return -1;
24434ba1faa1SWang Nan 		}
24444ba1faa1SWang Nan 
24454ba1faa1SWang Nan 		return 0;
24464ba1faa1SWang Nan 	}
24474ba1faa1SWang Nan 
24481e857484SMathieu Poirier 	while ((pmu = perf_pmu__scan(pmu)) != NULL)
24491fc632ceSJiri Olsa 		if (pmu->type == evsel->core.attr.type) {
24501e857484SMathieu Poirier 			found = true;
24511e857484SMathieu Poirier 			break;
24521e857484SMathieu Poirier 		}
24531e857484SMathieu Poirier 
24541e857484SMathieu Poirier 	if (found)
24551e857484SMathieu Poirier 		perf_pmu__scan_file(pmu, "nr_addr_filters",
24561e857484SMathieu Poirier 				    "%d", &nr_addr_filters);
24571e857484SMathieu Poirier 
2458d180aa56SNamhyung Kim 	if (!nr_addr_filters)
2459d180aa56SNamhyung Kim 		return perf_bpf_filter__parse(&evsel->bpf_filters, str);
24601e857484SMathieu Poirier 
2461ad681adfSArnaldo Carvalho de Melo 	if (evsel__append_addr_filter(evsel, str) < 0) {
24621e857484SMathieu Poirier 		fprintf(stderr,
24631e857484SMathieu Poirier 			"not enough memory to hold filter string\n");
24641e857484SMathieu Poirier 		return -1;
24651e857484SMathieu Poirier 	}
24661e857484SMathieu Poirier 
24671e857484SMathieu Poirier 	return 0;
24681e857484SMathieu Poirier }
24691e857484SMathieu Poirier 
24704ba1faa1SWang Nan int parse_filter(const struct option *opt, const char *str,
24714ba1faa1SWang Nan 		 int unset __maybe_unused)
24724ba1faa1SWang Nan {
247363503dbaSJiri Olsa 	struct evlist *evlist = *(struct evlist **)opt->value;
24744ba1faa1SWang Nan 
24754ba1faa1SWang Nan 	return foreach_evsel_in_last_glob(evlist, set_filter,
24764ba1faa1SWang Nan 					  (const void *)str);
24774ba1faa1SWang Nan }
24784ba1faa1SWang Nan 
247932dcd021SJiri Olsa static int add_exclude_perf_filter(struct evsel *evsel,
24804ba1faa1SWang Nan 				   const void *arg __maybe_unused)
24814ba1faa1SWang Nan {
24824ba1faa1SWang Nan 	char new_filter[64];
24834ba1faa1SWang Nan 
24841fc632ceSJiri Olsa 	if (evsel == NULL || evsel->core.attr.type != PERF_TYPE_TRACEPOINT) {
24854ba1faa1SWang Nan 		fprintf(stderr,
24864ba1faa1SWang Nan 			"--exclude-perf option should follow a -e tracepoint option\n");
24874ba1faa1SWang Nan 		return -1;
24884ba1faa1SWang Nan 	}
24894ba1faa1SWang Nan 
24904ba1faa1SWang Nan 	snprintf(new_filter, sizeof(new_filter), "common_pid != %d", getpid());
24914ba1faa1SWang Nan 
2492ad681adfSArnaldo Carvalho de Melo 	if (evsel__append_tp_filter(evsel, new_filter) < 0) {
24934ba1faa1SWang Nan 		fprintf(stderr,
24944ba1faa1SWang Nan 			"not enough memory to hold filter string\n");
24954ba1faa1SWang Nan 		return -1;
24964ba1faa1SWang Nan 	}
24974ba1faa1SWang Nan 
24984ba1faa1SWang Nan 	return 0;
24994ba1faa1SWang Nan }
25004ba1faa1SWang Nan 
25014ba1faa1SWang Nan int exclude_perf(const struct option *opt,
25024ba1faa1SWang Nan 		 const char *arg __maybe_unused,
25034ba1faa1SWang Nan 		 int unset __maybe_unused)
25044ba1faa1SWang Nan {
250563503dbaSJiri Olsa 	struct evlist *evlist = *(struct evlist **)opt->value;
25064ba1faa1SWang Nan 
25074ba1faa1SWang Nan 	return foreach_evsel_in_last_glob(evlist, add_exclude_perf_filter,
25084ba1faa1SWang Nan 					  NULL);
25094ba1faa1SWang Nan }
25104ba1faa1SWang Nan 
25116cee6cd3SArnaldo Carvalho de Melo int parse_events__is_hardcoded_term(struct parse_events_term *term)
25128f707d84SJiri Olsa {
251316fa7e82SJiri Olsa 	return term->type_term != PARSE_EVENTS__TERM_TYPE_USER;
25148f707d84SJiri Olsa }
25158f707d84SJiri Olsa 
251667b49b38SJiri Olsa static int new_term(struct parse_events_term **_term,
251767b49b38SJiri Olsa 		    struct parse_events_term *temp,
251867b49b38SJiri Olsa 		    char *str, u64 num)
25198f707d84SJiri Olsa {
25206cee6cd3SArnaldo Carvalho de Melo 	struct parse_events_term *term;
25218f707d84SJiri Olsa 
252267b49b38SJiri Olsa 	term = malloc(sizeof(*term));
25238f707d84SJiri Olsa 	if (!term)
25248f707d84SJiri Olsa 		return -ENOMEM;
25258f707d84SJiri Olsa 
252667b49b38SJiri Olsa 	*term = *temp;
25278f707d84SJiri Olsa 	INIT_LIST_HEAD(&term->list);
2528c2f1ceadSAndi Kleen 	term->weak = false;
25298f707d84SJiri Olsa 
253067b49b38SJiri Olsa 	switch (term->type_val) {
25318f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_NUM:
25328f707d84SJiri Olsa 		term->val.num = num;
25338f707d84SJiri Olsa 		break;
25348f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_STR:
25358f707d84SJiri Olsa 		term->val.str = str;
25368f707d84SJiri Olsa 		break;
25378f707d84SJiri Olsa 	default:
25384be8be6bSAdrian Hunter 		free(term);
25398f707d84SJiri Olsa 		return -EINVAL;
25408f707d84SJiri Olsa 	}
25418f707d84SJiri Olsa 
25428f707d84SJiri Olsa 	*_term = term;
25438f707d84SJiri Olsa 	return 0;
25448f707d84SJiri Olsa }
25458f707d84SJiri Olsa 
25466cee6cd3SArnaldo Carvalho de Melo int parse_events_term__num(struct parse_events_term **term,
2547cecf3a2eSJiri Olsa 			   int type_term, char *config, u64 num,
254899e7138eSJiri Olsa 			   bool no_value,
2549bb78ce7dSAdrian Hunter 			   void *loc_term_, void *loc_val_)
255016fa7e82SJiri Olsa {
2551bb78ce7dSAdrian Hunter 	YYLTYPE *loc_term = loc_term_;
2552bb78ce7dSAdrian Hunter 	YYLTYPE *loc_val = loc_val_;
2553bb78ce7dSAdrian Hunter 
255467b49b38SJiri Olsa 	struct parse_events_term temp = {
255567b49b38SJiri Olsa 		.type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
255667b49b38SJiri Olsa 		.type_term = type_term,
25574f9d4f8aSJohn Garry 		.config    = config ? : strdup(config_term_names[type_term]),
255899e7138eSJiri Olsa 		.no_value  = no_value,
255967b49b38SJiri Olsa 		.err_term  = loc_term ? loc_term->first_column : 0,
256067b49b38SJiri Olsa 		.err_val   = loc_val  ? loc_val->first_column  : 0,
256167b49b38SJiri Olsa 	};
256267b49b38SJiri Olsa 
256367b49b38SJiri Olsa 	return new_term(term, &temp, NULL, num);
256416fa7e82SJiri Olsa }
256516fa7e82SJiri Olsa 
25666cee6cd3SArnaldo Carvalho de Melo int parse_events_term__str(struct parse_events_term **term,
2567cecf3a2eSJiri Olsa 			   int type_term, char *config, char *str,
2568bb78ce7dSAdrian Hunter 			   void *loc_term_, void *loc_val_)
256916fa7e82SJiri Olsa {
2570bb78ce7dSAdrian Hunter 	YYLTYPE *loc_term = loc_term_;
2571bb78ce7dSAdrian Hunter 	YYLTYPE *loc_val = loc_val_;
2572bb78ce7dSAdrian Hunter 
257367b49b38SJiri Olsa 	struct parse_events_term temp = {
257467b49b38SJiri Olsa 		.type_val  = PARSE_EVENTS__TERM_TYPE_STR,
257567b49b38SJiri Olsa 		.type_term = type_term,
257667b49b38SJiri Olsa 		.config    = config,
257767b49b38SJiri Olsa 		.err_term  = loc_term ? loc_term->first_column : 0,
257867b49b38SJiri Olsa 		.err_val   = loc_val  ? loc_val->first_column  : 0,
257967b49b38SJiri Olsa 	};
258067b49b38SJiri Olsa 
258167b49b38SJiri Olsa 	return new_term(term, &temp, str, 0);
258216fa7e82SJiri Olsa }
258316fa7e82SJiri Olsa 
2584*e831f3ccSIan Rogers int parse_events_term__term(struct parse_events_term **term,
2585*e831f3ccSIan Rogers 			    int term_lhs, int term_rhs,
2586*e831f3ccSIan Rogers 			    void *loc_term, void *loc_val)
2587*e831f3ccSIan Rogers {
2588*e831f3ccSIan Rogers 	return parse_events_term__str(term, term_lhs, NULL,
2589*e831f3ccSIan Rogers 				      strdup(config_term_names[term_rhs]),
2590*e831f3ccSIan Rogers 				      loc_term, loc_val);
2591*e831f3ccSIan Rogers }
2592*e831f3ccSIan Rogers 
25936cee6cd3SArnaldo Carvalho de Melo int parse_events_term__clone(struct parse_events_term **new,
25946cee6cd3SArnaldo Carvalho de Melo 			     struct parse_events_term *term)
2595a6146d50SZheng Yan {
2596b6645a72SIan Rogers 	char *str;
259767b49b38SJiri Olsa 	struct parse_events_term temp = {
259867b49b38SJiri Olsa 		.type_val  = term->type_val,
259967b49b38SJiri Olsa 		.type_term = term->type_term,
2600b6645a72SIan Rogers 		.config    = NULL,
260167b49b38SJiri Olsa 		.err_term  = term->err_term,
260267b49b38SJiri Olsa 		.err_val   = term->err_val,
260367b49b38SJiri Olsa 	};
260467b49b38SJiri Olsa 
2605b6645a72SIan Rogers 	if (term->config) {
2606b6645a72SIan Rogers 		temp.config = strdup(term->config);
2607b6645a72SIan Rogers 		if (!temp.config)
2608b6645a72SIan Rogers 			return -ENOMEM;
2609b6645a72SIan Rogers 	}
2610b6645a72SIan Rogers 	if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM)
2611b6645a72SIan Rogers 		return new_term(new, &temp, NULL, term->val.num);
2612b6645a72SIan Rogers 
2613b6645a72SIan Rogers 	str = strdup(term->val.str);
2614b6645a72SIan Rogers 	if (!str)
2615b6645a72SIan Rogers 		return -ENOMEM;
2616b6645a72SIan Rogers 	return new_term(new, &temp, str, 0);
2617a6146d50SZheng Yan }
2618a6146d50SZheng Yan 
26191dc92556SIan Rogers void parse_events_term__delete(struct parse_events_term *term)
26201dc92556SIan Rogers {
26211dc92556SIan Rogers 	if (term->array.nr_ranges)
26221dc92556SIan Rogers 		zfree(&term->array.ranges);
26231dc92556SIan Rogers 
26241dc92556SIan Rogers 	if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM)
26251dc92556SIan Rogers 		zfree(&term->val.str);
26261dc92556SIan Rogers 
26271dc92556SIan Rogers 	zfree(&term->config);
26281dc92556SIan Rogers 	free(term);
26291dc92556SIan Rogers }
26301dc92556SIan Rogers 
26318255718fSAndi Kleen int parse_events_copy_term_list(struct list_head *old,
26328255718fSAndi Kleen 				 struct list_head **new)
26338255718fSAndi Kleen {
26348255718fSAndi Kleen 	struct parse_events_term *term, *n;
26358255718fSAndi Kleen 	int ret;
26368255718fSAndi Kleen 
26378255718fSAndi Kleen 	if (!old) {
26388255718fSAndi Kleen 		*new = NULL;
26398255718fSAndi Kleen 		return 0;
26408255718fSAndi Kleen 	}
26418255718fSAndi Kleen 
26428255718fSAndi Kleen 	*new = malloc(sizeof(struct list_head));
26438255718fSAndi Kleen 	if (!*new)
26448255718fSAndi Kleen 		return -ENOMEM;
26458255718fSAndi Kleen 	INIT_LIST_HEAD(*new);
26468255718fSAndi Kleen 
26478255718fSAndi Kleen 	list_for_each_entry (term, old, list) {
26488255718fSAndi Kleen 		ret = parse_events_term__clone(&n, term);
26498255718fSAndi Kleen 		if (ret)
26508255718fSAndi Kleen 			return ret;
26518255718fSAndi Kleen 		list_add_tail(&n->list, *new);
26528255718fSAndi Kleen 	}
26538255718fSAndi Kleen 	return 0;
26548255718fSAndi Kleen }
26558255718fSAndi Kleen 
2656fc0a2c1dSArnaldo Carvalho de Melo void parse_events_terms__purge(struct list_head *terms)
26578f707d84SJiri Olsa {
26586cee6cd3SArnaldo Carvalho de Melo 	struct parse_events_term *term, *h;
26598f707d84SJiri Olsa 
2660a8adfcebSWang Nan 	list_for_each_entry_safe(term, h, terms, list) {
2661a8adfcebSWang Nan 		list_del_init(&term->list);
26621dc92556SIan Rogers 		parse_events_term__delete(term);
26638f707d84SJiri Olsa 	}
2664a8adfcebSWang Nan }
2665b39b8393SJiri Olsa 
26662146afc6SArnaldo Carvalho de Melo void parse_events_terms__delete(struct list_head *terms)
2667fc0a2c1dSArnaldo Carvalho de Melo {
26682146afc6SArnaldo Carvalho de Melo 	if (!terms)
26692146afc6SArnaldo Carvalho de Melo 		return;
2670fc0a2c1dSArnaldo Carvalho de Melo 	parse_events_terms__purge(terms);
2671d20a5f2bSWang Nan 	free(terms);
2672fc0a2c1dSArnaldo Carvalho de Melo }
2673fc0a2c1dSArnaldo Carvalho de Melo 
26742d055bf2SWang Nan void parse_events__clear_array(struct parse_events_array *a)
26752d055bf2SWang Nan {
2676360e071bSTaeung Song 	zfree(&a->ranges);
26772d055bf2SWang Nan }
26782d055bf2SWang Nan 
26795d9cdc11SArnaldo Carvalho de Melo void parse_events_evlist_error(struct parse_events_state *parse_state,
2680b39b8393SJiri Olsa 			       int idx, const char *str)
2681b39b8393SJiri Olsa {
2682448d732cSIan Rogers 	if (!parse_state->error)
2683a6ced2beSAdrian Hunter 		return;
2684448d732cSIan Rogers 
26856c191289SIan Rogers 	parse_events_error__handle(parse_state->error, idx, strdup(str), NULL);
2686b39b8393SJiri Olsa }
2687ffeb883eSHe Kuang 
268817cb5f84SWang Nan static void config_terms_list(char *buf, size_t buf_sz)
268917cb5f84SWang Nan {
269017cb5f84SWang Nan 	int i;
269117cb5f84SWang Nan 	bool first = true;
269217cb5f84SWang Nan 
269317cb5f84SWang Nan 	buf[0] = '\0';
269417cb5f84SWang Nan 	for (i = 0; i < __PARSE_EVENTS__TERM_TYPE_NR; i++) {
269517cb5f84SWang Nan 		const char *name = config_term_names[i];
269617cb5f84SWang Nan 
26971669e509SWang Nan 		if (!config_term_avail(i, NULL))
26981669e509SWang Nan 			continue;
269917cb5f84SWang Nan 		if (!name)
270017cb5f84SWang Nan 			continue;
270117cb5f84SWang Nan 		if (name[0] == '<')
270217cb5f84SWang Nan 			continue;
270317cb5f84SWang Nan 
270417cb5f84SWang Nan 		if (strlen(buf) + strlen(name) + 2 >= buf_sz)
270517cb5f84SWang Nan 			return;
270617cb5f84SWang Nan 
270717cb5f84SWang Nan 		if (!first)
270817cb5f84SWang Nan 			strcat(buf, ",");
270917cb5f84SWang Nan 		else
271017cb5f84SWang Nan 			first = false;
271117cb5f84SWang Nan 		strcat(buf, name);
271217cb5f84SWang Nan 	}
271317cb5f84SWang Nan }
271417cb5f84SWang Nan 
2715ffeb883eSHe Kuang /*
2716ffeb883eSHe Kuang  * Return string contains valid config terms of an event.
2717ffeb883eSHe Kuang  * @additional_terms: For terms such as PMU sysfs terms.
2718ffeb883eSHe Kuang  */
2719ffeb883eSHe Kuang char *parse_events_formats_error_string(char *additional_terms)
2720ffeb883eSHe Kuang {
2721ffeb883eSHe Kuang 	char *str;
2722626a6b78SWang Nan 	/* "no-overwrite" is the longest name */
272317cb5f84SWang Nan 	char static_terms[__PARSE_EVENTS__TERM_TYPE_NR *
2724626a6b78SWang Nan 			  (sizeof("no-overwrite") - 1)];
2725ffeb883eSHe Kuang 
272617cb5f84SWang Nan 	config_terms_list(static_terms, sizeof(static_terms));
2727ffeb883eSHe Kuang 	/* valid terms */
2728ffeb883eSHe Kuang 	if (additional_terms) {
272926dee028SWang Nan 		if (asprintf(&str, "valid terms: %s,%s",
273026dee028SWang Nan 			     additional_terms, static_terms) < 0)
2731ffeb883eSHe Kuang 			goto fail;
2732ffeb883eSHe Kuang 	} else {
273326dee028SWang Nan 		if (asprintf(&str, "valid terms: %s", static_terms) < 0)
2734ffeb883eSHe Kuang 			goto fail;
2735ffeb883eSHe Kuang 	}
2736ffeb883eSHe Kuang 	return str;
2737ffeb883eSHe Kuang 
2738ffeb883eSHe Kuang fail:
2739ffeb883eSHe Kuang 	return NULL;
2740ffeb883eSHe Kuang }
2741