xref: /linux/tools/perf/util/parse-events.c (revision e571e029bdbf59f485fe67740b7a4ef421e1d55d)
1d2709c7cSDavid Howells #include <linux/hw_breakpoint.h>
28dd2a131SJiri Olsa #include <linux/err.h>
386470930SIngo Molnar #include "util.h"
46b58e7f1SUlrich Drepper #include "../perf.h"
5361c99a6SArnaldo Carvalho de Melo #include "evlist.h"
669aad6f1SArnaldo Carvalho de Melo #include "evsel.h"
74b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h>
886470930SIngo Molnar #include "parse-events.h"
94b6ab94eSJosh Poimboeuf #include <subcmd/exec-cmd.h>
1042f60c2dSKan Liang #include "string.h"
115aab621bSArnaldo Carvalho de Melo #include "symbol.h"
125beeded1SJason Baron #include "cache.h"
138755a8f2SArjan van de Ven #include "header.h"
1484c86ca1SWang Nan #include "bpf-loader.h"
156e81c74cSMasami Hiramatsu #include "debug.h"
16592d5a6bSJiri Olsa #include <api/fs/tracing_path.h>
17ac20de6fSZheng Yan #include "parse-events-bison.h"
1890e2b22dSJiri Olsa #define YY_EXTRA_TYPE int
1989812fc8SJiri Olsa #include "parse-events-flex.h"
205f537a26SJiri Olsa #include "pmu.h"
21b41f1cecSNamhyung Kim #include "thread_map.h"
22f30a79b0SJiri Olsa #include "cpumap.h"
23b39b8393SJiri Olsa #include "asm/bug.h"
2489812fc8SJiri Olsa 
2589812fc8SJiri Olsa #define MAX_NAME_LEN 100
2686470930SIngo Molnar 
2782ba1f2fSJiri Olsa #ifdef PARSER_DEBUG
2882ba1f2fSJiri Olsa extern int parse_events_debug;
2982ba1f2fSJiri Olsa #endif
30ac20de6fSZheng Yan int parse_events_parse(void *data, void *scanner);
31e637d177SHe Kuang static int get_config_terms(struct list_head *head_config,
32e637d177SHe Kuang 			    struct list_head *head_terms __maybe_unused);
33bcd3279fSFrederic Weisbecker 
34dcb4e102SKan Liang static struct perf_pmu_event_symbol *perf_pmu_events_list;
35dcb4e102SKan Liang /*
36dcb4e102SKan Liang  * The variable indicates the number of supported pmu event symbols.
37dcb4e102SKan Liang  * 0 means not initialized and ready to init
38dcb4e102SKan Liang  * -1 means failed to init, don't try anymore
39dcb4e102SKan Liang  * >0 is the number of supported pmu event symbols
40dcb4e102SKan Liang  */
41dcb4e102SKan Liang static int perf_pmu_events_list_num;
42dcb4e102SKan Liang 
43705750f2SYunlong Song struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = {
441dc12760SJiri Olsa 	[PERF_COUNT_HW_CPU_CYCLES] = {
451dc12760SJiri Olsa 		.symbol = "cpu-cycles",
461dc12760SJiri Olsa 		.alias  = "cycles",
471dc12760SJiri Olsa 	},
481dc12760SJiri Olsa 	[PERF_COUNT_HW_INSTRUCTIONS] = {
491dc12760SJiri Olsa 		.symbol = "instructions",
501dc12760SJiri Olsa 		.alias  = "",
511dc12760SJiri Olsa 	},
521dc12760SJiri Olsa 	[PERF_COUNT_HW_CACHE_REFERENCES] = {
531dc12760SJiri Olsa 		.symbol = "cache-references",
541dc12760SJiri Olsa 		.alias  = "",
551dc12760SJiri Olsa 	},
561dc12760SJiri Olsa 	[PERF_COUNT_HW_CACHE_MISSES] = {
571dc12760SJiri Olsa 		.symbol = "cache-misses",
581dc12760SJiri Olsa 		.alias  = "",
591dc12760SJiri Olsa 	},
601dc12760SJiri Olsa 	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = {
611dc12760SJiri Olsa 		.symbol = "branch-instructions",
621dc12760SJiri Olsa 		.alias  = "branches",
631dc12760SJiri Olsa 	},
641dc12760SJiri Olsa 	[PERF_COUNT_HW_BRANCH_MISSES] = {
651dc12760SJiri Olsa 		.symbol = "branch-misses",
661dc12760SJiri Olsa 		.alias  = "",
671dc12760SJiri Olsa 	},
681dc12760SJiri Olsa 	[PERF_COUNT_HW_BUS_CYCLES] = {
691dc12760SJiri Olsa 		.symbol = "bus-cycles",
701dc12760SJiri Olsa 		.alias  = "",
711dc12760SJiri Olsa 	},
721dc12760SJiri Olsa 	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = {
731dc12760SJiri Olsa 		.symbol = "stalled-cycles-frontend",
741dc12760SJiri Olsa 		.alias  = "idle-cycles-frontend",
751dc12760SJiri Olsa 	},
761dc12760SJiri Olsa 	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = {
771dc12760SJiri Olsa 		.symbol = "stalled-cycles-backend",
781dc12760SJiri Olsa 		.alias  = "idle-cycles-backend",
791dc12760SJiri Olsa 	},
801dc12760SJiri Olsa 	[PERF_COUNT_HW_REF_CPU_CYCLES] = {
811dc12760SJiri Olsa 		.symbol = "ref-cycles",
821dc12760SJiri Olsa 		.alias  = "",
831dc12760SJiri Olsa 	},
841dc12760SJiri Olsa };
8586470930SIngo Molnar 
86705750f2SYunlong Song struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
871dc12760SJiri Olsa 	[PERF_COUNT_SW_CPU_CLOCK] = {
881dc12760SJiri Olsa 		.symbol = "cpu-clock",
891dc12760SJiri Olsa 		.alias  = "",
901dc12760SJiri Olsa 	},
911dc12760SJiri Olsa 	[PERF_COUNT_SW_TASK_CLOCK] = {
921dc12760SJiri Olsa 		.symbol = "task-clock",
931dc12760SJiri Olsa 		.alias  = "",
941dc12760SJiri Olsa 	},
951dc12760SJiri Olsa 	[PERF_COUNT_SW_PAGE_FAULTS] = {
961dc12760SJiri Olsa 		.symbol = "page-faults",
971dc12760SJiri Olsa 		.alias  = "faults",
981dc12760SJiri Olsa 	},
991dc12760SJiri Olsa 	[PERF_COUNT_SW_CONTEXT_SWITCHES] = {
1001dc12760SJiri Olsa 		.symbol = "context-switches",
1011dc12760SJiri Olsa 		.alias  = "cs",
1021dc12760SJiri Olsa 	},
1031dc12760SJiri Olsa 	[PERF_COUNT_SW_CPU_MIGRATIONS] = {
1041dc12760SJiri Olsa 		.symbol = "cpu-migrations",
1051dc12760SJiri Olsa 		.alias  = "migrations",
1061dc12760SJiri Olsa 	},
1071dc12760SJiri Olsa 	[PERF_COUNT_SW_PAGE_FAULTS_MIN] = {
1081dc12760SJiri Olsa 		.symbol = "minor-faults",
1091dc12760SJiri Olsa 		.alias  = "",
1101dc12760SJiri Olsa 	},
1111dc12760SJiri Olsa 	[PERF_COUNT_SW_PAGE_FAULTS_MAJ] = {
1121dc12760SJiri Olsa 		.symbol = "major-faults",
1131dc12760SJiri Olsa 		.alias  = "",
1141dc12760SJiri Olsa 	},
1151dc12760SJiri Olsa 	[PERF_COUNT_SW_ALIGNMENT_FAULTS] = {
1161dc12760SJiri Olsa 		.symbol = "alignment-faults",
1171dc12760SJiri Olsa 		.alias  = "",
1181dc12760SJiri Olsa 	},
1191dc12760SJiri Olsa 	[PERF_COUNT_SW_EMULATION_FAULTS] = {
1201dc12760SJiri Olsa 		.symbol = "emulation-faults",
1211dc12760SJiri Olsa 		.alias  = "",
1221dc12760SJiri Olsa 	},
123d22d1a2aSAdrian Hunter 	[PERF_COUNT_SW_DUMMY] = {
124d22d1a2aSAdrian Hunter 		.symbol = "dummy",
125d22d1a2aSAdrian Hunter 		.alias  = "",
126d22d1a2aSAdrian Hunter 	},
127bae9cc41SArnaldo Carvalho de Melo 	[PERF_COUNT_SW_BPF_OUTPUT] = {
128bae9cc41SArnaldo Carvalho de Melo 		.symbol = "bpf-output",
129bae9cc41SArnaldo Carvalho de Melo 		.alias  = "",
130bae9cc41SArnaldo Carvalho de Melo 	},
13186470930SIngo Molnar };
13286470930SIngo Molnar 
133cdd6c482SIngo Molnar #define __PERF_EVENT_FIELD(config, name) \
134cdd6c482SIngo Molnar 	((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT)
13586470930SIngo Molnar 
136cdd6c482SIngo Molnar #define PERF_EVENT_RAW(config)		__PERF_EVENT_FIELD(config, RAW)
137cdd6c482SIngo Molnar #define PERF_EVENT_CONFIG(config)	__PERF_EVENT_FIELD(config, CONFIG)
138cdd6c482SIngo Molnar #define PERF_EVENT_TYPE(config)		__PERF_EVENT_FIELD(config, TYPE)
139cdd6c482SIngo Molnar #define PERF_EVENT_ID(config)		__PERF_EVENT_FIELD(config, EVENT)
14086470930SIngo Molnar 
1416b58e7f1SUlrich Drepper #define for_each_subsystem(sys_dir, sys_dirent, sys_next)	       \
142f6bdafefSJason Baron 	while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next)	       \
1436b58e7f1SUlrich Drepper 	if (sys_dirent.d_type == DT_DIR &&				       \
144f6bdafefSJason Baron 	   (strcmp(sys_dirent.d_name, ".")) &&				       \
145f6bdafefSJason Baron 	   (strcmp(sys_dirent.d_name, "..")))
146f6bdafefSJason Baron 
147ae07b63fSPeter Zijlstra static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
148ae07b63fSPeter Zijlstra {
149ae07b63fSPeter Zijlstra 	char evt_path[MAXPATHLEN];
150ae07b63fSPeter Zijlstra 	int fd;
151ae07b63fSPeter Zijlstra 
152ebf294bfSArnaldo Carvalho de Melo 	snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path,
153ae07b63fSPeter Zijlstra 			sys_dir->d_name, evt_dir->d_name);
154ae07b63fSPeter Zijlstra 	fd = open(evt_path, O_RDONLY);
155ae07b63fSPeter Zijlstra 	if (fd < 0)
156ae07b63fSPeter Zijlstra 		return -EINVAL;
157ae07b63fSPeter Zijlstra 	close(fd);
158ae07b63fSPeter Zijlstra 
159ae07b63fSPeter Zijlstra 	return 0;
160ae07b63fSPeter Zijlstra }
161ae07b63fSPeter Zijlstra 
1626b58e7f1SUlrich Drepper #define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next)	       \
163f6bdafefSJason Baron 	while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next)        \
1646b58e7f1SUlrich Drepper 	if (evt_dirent.d_type == DT_DIR &&				       \
165f6bdafefSJason Baron 	   (strcmp(evt_dirent.d_name, ".")) &&				       \
166ae07b63fSPeter Zijlstra 	   (strcmp(evt_dirent.d_name, "..")) &&				       \
167ae07b63fSPeter Zijlstra 	   (!tp_event_has_id(&sys_dirent, &evt_dirent)))
168f6bdafefSJason Baron 
169270bbbe8SLi Zefan #define MAX_EVENT_LENGTH 512
170f6bdafefSJason Baron 
171f6bdafefSJason Baron 
1721ef2ed10SFrederic Weisbecker struct tracepoint_path *tracepoint_id_to_path(u64 config)
173f6bdafefSJason Baron {
1741ef2ed10SFrederic Weisbecker 	struct tracepoint_path *path = NULL;
175f6bdafefSJason Baron 	DIR *sys_dir, *evt_dir;
176f6bdafefSJason Baron 	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
1778aa8a7c8SStephane Eranian 	char id_buf[24];
178725b1368SEric Dumazet 	int fd;
179f6bdafefSJason Baron 	u64 id;
180f6bdafefSJason Baron 	char evt_path[MAXPATHLEN];
181725b1368SEric Dumazet 	char dir_path[MAXPATHLEN];
182f6bdafefSJason Baron 
183ebf294bfSArnaldo Carvalho de Melo 	sys_dir = opendir(tracing_events_path);
184f6bdafefSJason Baron 	if (!sys_dir)
185725b1368SEric Dumazet 		return NULL;
186f6bdafefSJason Baron 
1876b58e7f1SUlrich Drepper 	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
188725b1368SEric Dumazet 
189ebf294bfSArnaldo Carvalho de Melo 		snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
190725b1368SEric Dumazet 			 sys_dirent.d_name);
191725b1368SEric Dumazet 		evt_dir = opendir(dir_path);
192725b1368SEric Dumazet 		if (!evt_dir)
1936b58e7f1SUlrich Drepper 			continue;
194725b1368SEric Dumazet 
1956b58e7f1SUlrich Drepper 		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
196725b1368SEric Dumazet 
197725b1368SEric Dumazet 			snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
198f6bdafefSJason Baron 				 evt_dirent.d_name);
199725b1368SEric Dumazet 			fd = open(evt_path, O_RDONLY);
200f6bdafefSJason Baron 			if (fd < 0)
201f6bdafefSJason Baron 				continue;
202f6bdafefSJason Baron 			if (read(fd, id_buf, sizeof(id_buf)) < 0) {
203f6bdafefSJason Baron 				close(fd);
204f6bdafefSJason Baron 				continue;
205f6bdafefSJason Baron 			}
206f6bdafefSJason Baron 			close(fd);
207f6bdafefSJason Baron 			id = atoll(id_buf);
208f6bdafefSJason Baron 			if (id == config) {
209f6bdafefSJason Baron 				closedir(evt_dir);
210f6bdafefSJason Baron 				closedir(sys_dir);
21159b4caebSJulia Lawall 				path = zalloc(sizeof(*path));
2121ef2ed10SFrederic Weisbecker 				path->system = malloc(MAX_EVENT_LENGTH);
2131ef2ed10SFrederic Weisbecker 				if (!path->system) {
2141ef2ed10SFrederic Weisbecker 					free(path);
2151ef2ed10SFrederic Weisbecker 					return NULL;
2161ef2ed10SFrederic Weisbecker 				}
2171ef2ed10SFrederic Weisbecker 				path->name = malloc(MAX_EVENT_LENGTH);
2181ef2ed10SFrederic Weisbecker 				if (!path->name) {
21974cf249dSArnaldo Carvalho de Melo 					zfree(&path->system);
2201ef2ed10SFrederic Weisbecker 					free(path);
2211ef2ed10SFrederic Weisbecker 					return NULL;
2221ef2ed10SFrederic Weisbecker 				}
2231ef2ed10SFrederic Weisbecker 				strncpy(path->system, sys_dirent.d_name,
2241ef2ed10SFrederic Weisbecker 					MAX_EVENT_LENGTH);
2251ef2ed10SFrederic Weisbecker 				strncpy(path->name, evt_dirent.d_name,
2261ef2ed10SFrederic Weisbecker 					MAX_EVENT_LENGTH);
2271ef2ed10SFrederic Weisbecker 				return path;
228f6bdafefSJason Baron 			}
229f6bdafefSJason Baron 		}
230f6bdafefSJason Baron 		closedir(evt_dir);
231f6bdafefSJason Baron 	}
232f6bdafefSJason Baron 
233f6bdafefSJason Baron 	closedir(sys_dir);
2341ef2ed10SFrederic Weisbecker 	return NULL;
2351ef2ed10SFrederic Weisbecker }
2361ef2ed10SFrederic Weisbecker 
237e7c93f09SNamhyung Kim struct tracepoint_path *tracepoint_name_to_path(const char *name)
238e7c93f09SNamhyung Kim {
239e7c93f09SNamhyung Kim 	struct tracepoint_path *path = zalloc(sizeof(*path));
240e7c93f09SNamhyung Kim 	char *str = strchr(name, ':');
241e7c93f09SNamhyung Kim 
242e7c93f09SNamhyung Kim 	if (path == NULL || str == NULL) {
243e7c93f09SNamhyung Kim 		free(path);
244e7c93f09SNamhyung Kim 		return NULL;
245e7c93f09SNamhyung Kim 	}
246e7c93f09SNamhyung Kim 
247e7c93f09SNamhyung Kim 	path->system = strndup(name, str - name);
248e7c93f09SNamhyung Kim 	path->name = strdup(str+1);
249e7c93f09SNamhyung Kim 
250e7c93f09SNamhyung Kim 	if (path->system == NULL || path->name == NULL) {
25174cf249dSArnaldo Carvalho de Melo 		zfree(&path->system);
25274cf249dSArnaldo Carvalho de Melo 		zfree(&path->name);
253e7c93f09SNamhyung Kim 		free(path);
254e7c93f09SNamhyung Kim 		path = NULL;
255e7c93f09SNamhyung Kim 	}
256e7c93f09SNamhyung Kim 
257e7c93f09SNamhyung Kim 	return path;
258e7c93f09SNamhyung Kim }
259e7c93f09SNamhyung Kim 
2601424dc96SDavid Ahern const char *event_type(int type)
2611424dc96SDavid Ahern {
2621424dc96SDavid Ahern 	switch (type) {
2631424dc96SDavid Ahern 	case PERF_TYPE_HARDWARE:
2641424dc96SDavid Ahern 		return "hardware";
2651424dc96SDavid Ahern 
2661424dc96SDavid Ahern 	case PERF_TYPE_SOFTWARE:
2671424dc96SDavid Ahern 		return "software";
2681424dc96SDavid Ahern 
2691424dc96SDavid Ahern 	case PERF_TYPE_TRACEPOINT:
2701424dc96SDavid Ahern 		return "tracepoint";
2711424dc96SDavid Ahern 
2721424dc96SDavid Ahern 	case PERF_TYPE_HW_CACHE:
2731424dc96SDavid Ahern 		return "hardware-cache";
2741424dc96SDavid Ahern 
2751424dc96SDavid Ahern 	default:
2761424dc96SDavid Ahern 		break;
2771424dc96SDavid Ahern 	}
2781424dc96SDavid Ahern 
2791424dc96SDavid Ahern 	return "unknown";
2801424dc96SDavid Ahern }
2811424dc96SDavid Ahern 
282e814fdddSWang Nan static int parse_events__is_name_term(struct parse_events_term *term)
283e814fdddSWang Nan {
284e814fdddSWang Nan 	return term->type_term == PARSE_EVENTS__TERM_TYPE_NAME;
285e814fdddSWang Nan }
2867ae92e74SYan, Zheng 
287e814fdddSWang Nan static char *get_config_name(struct list_head *head_terms)
288e814fdddSWang Nan {
289e814fdddSWang Nan 	struct parse_events_term *term;
290e814fdddSWang Nan 
291e814fdddSWang Nan 	if (!head_terms)
292e814fdddSWang Nan 		return NULL;
293e814fdddSWang Nan 
294e814fdddSWang Nan 	list_for_each_entry(term, head_terms, list)
295e814fdddSWang Nan 		if (parse_events__is_name_term(term))
296e814fdddSWang Nan 			return term->val.str;
297e814fdddSWang Nan 
298e814fdddSWang Nan 	return NULL;
299e814fdddSWang Nan }
3007ae92e74SYan, Zheng 
301410136f5SStephane Eranian static struct perf_evsel *
302410136f5SStephane Eranian __add_event(struct list_head *list, int *idx,
3037ae92e74SYan, Zheng 	    struct perf_event_attr *attr,
304930a2e29SJiri Olsa 	    char *name, struct cpu_map *cpus,
305930a2e29SJiri Olsa 	    struct list_head *config_terms)
30689812fc8SJiri Olsa {
30789812fc8SJiri Olsa 	struct perf_evsel *evsel;
30889812fc8SJiri Olsa 
30989812fc8SJiri Olsa 	event_attr_init(attr);
31089812fc8SJiri Olsa 
311ef503831SArnaldo Carvalho de Melo 	evsel = perf_evsel__new_idx(attr, (*idx)++);
312c5cd8ac0SDavid Ahern 	if (!evsel)
313410136f5SStephane Eranian 		return NULL;
31489812fc8SJiri Olsa 
315f30a79b0SJiri Olsa 	evsel->cpus     = cpu_map__get(cpus);
316fce4d296SAdrian Hunter 	evsel->own_cpus = cpu_map__get(cpus);
317f30a79b0SJiri Olsa 
3189db1763cSArnaldo Carvalho de Melo 	if (name)
31989812fc8SJiri Olsa 		evsel->name = strdup(name);
320930a2e29SJiri Olsa 
321930a2e29SJiri Olsa 	if (config_terms)
322930a2e29SJiri Olsa 		list_splice(config_terms, &evsel->config_terms);
323930a2e29SJiri Olsa 
324b847cbdcSJiri Olsa 	list_add_tail(&evsel->node, list);
325410136f5SStephane Eranian 	return evsel;
32689812fc8SJiri Olsa }
32789812fc8SJiri Olsa 
328c5cd8ac0SDavid Ahern static int add_event(struct list_head *list, int *idx,
329930a2e29SJiri Olsa 		     struct perf_event_attr *attr, char *name,
330930a2e29SJiri Olsa 		     struct list_head *config_terms)
3317ae92e74SYan, Zheng {
332930a2e29SJiri Olsa 	return __add_event(list, idx, attr, name, NULL, config_terms) ? 0 : -ENOMEM;
3337ae92e74SYan, Zheng }
3347ae92e74SYan, Zheng 
3350b668bc9SArnaldo Carvalho de Melo static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)
33686470930SIngo Molnar {
33786470930SIngo Molnar 	int i, j;
33861c45981SPaul Mackerras 	int n, longest = -1;
33986470930SIngo Molnar 
34086470930SIngo Molnar 	for (i = 0; i < size; i++) {
3410b668bc9SArnaldo Carvalho de Melo 		for (j = 0; j < PERF_EVSEL__MAX_ALIASES && names[i][j]; j++) {
34261c45981SPaul Mackerras 			n = strlen(names[i][j]);
34389812fc8SJiri Olsa 			if (n > longest && !strncasecmp(str, names[i][j], n))
34461c45981SPaul Mackerras 				longest = n;
34561c45981SPaul Mackerras 		}
34689812fc8SJiri Olsa 		if (longest > 0)
34786470930SIngo Molnar 			return i;
34886470930SIngo Molnar 	}
34986470930SIngo Molnar 
3508953645fSIngo Molnar 	return -1;
35186470930SIngo Molnar }
35286470930SIngo Molnar 
35343d0b978SWang Nan typedef int config_term_func_t(struct perf_event_attr *attr,
35443d0b978SWang Nan 			       struct parse_events_term *term,
35543d0b978SWang Nan 			       struct parse_events_error *err);
35643d0b978SWang Nan static int config_term_common(struct perf_event_attr *attr,
35743d0b978SWang Nan 			      struct parse_events_term *term,
35843d0b978SWang Nan 			      struct parse_events_error *err);
35943d0b978SWang Nan static int config_attr(struct perf_event_attr *attr,
36043d0b978SWang Nan 		       struct list_head *head,
36143d0b978SWang Nan 		       struct parse_events_error *err,
36243d0b978SWang Nan 		       config_term_func_t config_term);
36343d0b978SWang Nan 
364c5cd8ac0SDavid Ahern int parse_events_add_cache(struct list_head *list, int *idx,
36543d0b978SWang Nan 			   char *type, char *op_result1, char *op_result2,
3662c97b0d4SArnaldo Carvalho de Melo 			   struct parse_events_error *err,
36743d0b978SWang Nan 			   struct list_head *head_config)
36886470930SIngo Molnar {
36989812fc8SJiri Olsa 	struct perf_event_attr attr;
37043d0b978SWang Nan 	LIST_HEAD(config_terms);
37143d0b978SWang Nan 	char name[MAX_NAME_LEN], *config_name;
37261c45981SPaul Mackerras 	int cache_type = -1, cache_op = -1, cache_result = -1;
37389812fc8SJiri Olsa 	char *op_result[2] = { op_result1, op_result2 };
37489812fc8SJiri Olsa 	int i, n;
37586470930SIngo Molnar 
37686470930SIngo Molnar 	/*
37786470930SIngo Molnar 	 * No fallback - if we cannot get a clear cache type
37886470930SIngo Molnar 	 * then bail out:
37986470930SIngo Molnar 	 */
3800b668bc9SArnaldo Carvalho de Melo 	cache_type = parse_aliases(type, perf_evsel__hw_cache,
38189812fc8SJiri Olsa 				   PERF_COUNT_HW_CACHE_MAX);
38286470930SIngo Molnar 	if (cache_type == -1)
38389812fc8SJiri Olsa 		return -EINVAL;
38486470930SIngo Molnar 
38543d0b978SWang Nan 	config_name = get_config_name(head_config);
38689812fc8SJiri Olsa 	n = snprintf(name, MAX_NAME_LEN, "%s", type);
38789812fc8SJiri Olsa 
38889812fc8SJiri Olsa 	for (i = 0; (i < 2) && (op_result[i]); i++) {
38989812fc8SJiri Olsa 		char *str = op_result[i];
39089812fc8SJiri Olsa 
391275ef387SJiri Olsa 		n += snprintf(name + n, MAX_NAME_LEN - n, "-%s", str);
39261c45981SPaul Mackerras 
39361c45981SPaul Mackerras 		if (cache_op == -1) {
3940b668bc9SArnaldo Carvalho de Melo 			cache_op = parse_aliases(str, perf_evsel__hw_cache_op,
39561c45981SPaul Mackerras 						 PERF_COUNT_HW_CACHE_OP_MAX);
39661c45981SPaul Mackerras 			if (cache_op >= 0) {
3970b668bc9SArnaldo Carvalho de Melo 				if (!perf_evsel__is_cache_op_valid(cache_type, cache_op))
39889812fc8SJiri Olsa 					return -EINVAL;
39961c45981SPaul Mackerras 				continue;
40061c45981SPaul Mackerras 			}
40161c45981SPaul Mackerras 		}
40261c45981SPaul Mackerras 
40361c45981SPaul Mackerras 		if (cache_result == -1) {
4040b668bc9SArnaldo Carvalho de Melo 			cache_result = parse_aliases(str, perf_evsel__hw_cache_result,
40561c45981SPaul Mackerras 						     PERF_COUNT_HW_CACHE_RESULT_MAX);
40661c45981SPaul Mackerras 			if (cache_result >= 0)
40761c45981SPaul Mackerras 				continue;
40861c45981SPaul Mackerras 		}
40961c45981SPaul Mackerras 	}
41061c45981SPaul Mackerras 
41186470930SIngo Molnar 	/*
41286470930SIngo Molnar 	 * Fall back to reads:
41386470930SIngo Molnar 	 */
4148953645fSIngo Molnar 	if (cache_op == -1)
4158953645fSIngo Molnar 		cache_op = PERF_COUNT_HW_CACHE_OP_READ;
41686470930SIngo Molnar 
41786470930SIngo Molnar 	/*
41886470930SIngo Molnar 	 * Fall back to accesses:
41986470930SIngo Molnar 	 */
42086470930SIngo Molnar 	if (cache_result == -1)
42186470930SIngo Molnar 		cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS;
42286470930SIngo Molnar 
42389812fc8SJiri Olsa 	memset(&attr, 0, sizeof(attr));
42489812fc8SJiri Olsa 	attr.config = cache_type | (cache_op << 8) | (cache_result << 16);
42589812fc8SJiri Olsa 	attr.type = PERF_TYPE_HW_CACHE;
42643d0b978SWang Nan 
42743d0b978SWang Nan 	if (head_config) {
4282c97b0d4SArnaldo Carvalho de Melo 		if (config_attr(&attr, head_config, err,
42943d0b978SWang Nan 				config_term_common))
43043d0b978SWang Nan 			return -EINVAL;
43143d0b978SWang Nan 
43243d0b978SWang Nan 		if (get_config_terms(head_config, &config_terms))
43343d0b978SWang Nan 			return -ENOMEM;
43443d0b978SWang Nan 	}
43543d0b978SWang Nan 	return add_event(list, idx, &attr, config_name ? : name, &config_terms);
43686470930SIngo Molnar }
43786470930SIngo Molnar 
438272ed29aSJiri Olsa static void tracepoint_error(struct parse_events_error *e, int err,
43919658171SJiri Olsa 			     char *sys, char *name)
44019658171SJiri Olsa {
44119658171SJiri Olsa 	char help[BUFSIZ];
44219658171SJiri Olsa 
443ec183d22SAdrian Hunter 	if (!e)
444ec183d22SAdrian Hunter 		return;
445ec183d22SAdrian Hunter 
44619658171SJiri Olsa 	/*
44719658171SJiri Olsa 	 * We get error directly from syscall errno ( > 0),
44819658171SJiri Olsa 	 * or from encoded pointer's error ( < 0).
44919658171SJiri Olsa 	 */
45019658171SJiri Olsa 	err = abs(err);
45119658171SJiri Olsa 
45219658171SJiri Olsa 	switch (err) {
45319658171SJiri Olsa 	case EACCES:
454272ed29aSJiri Olsa 		e->str = strdup("can't access trace events");
45519658171SJiri Olsa 		break;
45619658171SJiri Olsa 	case ENOENT:
457272ed29aSJiri Olsa 		e->str = strdup("unknown tracepoint");
45819658171SJiri Olsa 		break;
45919658171SJiri Olsa 	default:
460272ed29aSJiri Olsa 		e->str = strdup("failed to add tracepoint");
46119658171SJiri Olsa 		break;
46219658171SJiri Olsa 	}
46319658171SJiri Olsa 
46419658171SJiri Olsa 	tracing_path__strerror_open_tp(err, help, sizeof(help), sys, name);
465272ed29aSJiri Olsa 	e->help = strdup(help);
46619658171SJiri Olsa }
46719658171SJiri Olsa 
468c5cd8ac0SDavid Ahern static int add_tracepoint(struct list_head *list, int *idx,
469e2f9f8eaSJiri Olsa 			  char *sys_name, char *evt_name,
470272ed29aSJiri Olsa 			  struct parse_events_error *err,
471e637d177SHe Kuang 			  struct list_head *head_config)
472bcd3279fSFrederic Weisbecker {
47382fe1c29SArnaldo Carvalho de Melo 	struct perf_evsel *evsel;
474bcd3279fSFrederic Weisbecker 
475ef503831SArnaldo Carvalho de Melo 	evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++);
47619658171SJiri Olsa 	if (IS_ERR(evsel)) {
477272ed29aSJiri Olsa 		tracepoint_error(err, PTR_ERR(evsel), sys_name, evt_name);
4788dd2a131SJiri Olsa 		return PTR_ERR(evsel);
47919658171SJiri Olsa 	}
480bcd3279fSFrederic Weisbecker 
481e637d177SHe Kuang 	if (head_config) {
482e637d177SHe Kuang 		LIST_HEAD(config_terms);
483e637d177SHe Kuang 
484e637d177SHe Kuang 		if (get_config_terms(head_config, &config_terms))
485e637d177SHe Kuang 			return -ENOMEM;
486e637d177SHe Kuang 		list_splice(&config_terms, &evsel->config_terms);
487e637d177SHe Kuang 	}
488e637d177SHe Kuang 
48982fe1c29SArnaldo Carvalho de Melo 	list_add_tail(&evsel->node, list);
49082fe1c29SArnaldo Carvalho de Melo 	return 0;
491bcd3279fSFrederic Weisbecker }
492bcd3279fSFrederic Weisbecker 
493c5cd8ac0SDavid Ahern static int add_tracepoint_multi_event(struct list_head *list, int *idx,
494e2f9f8eaSJiri Olsa 				      char *sys_name, char *evt_name,
495272ed29aSJiri Olsa 				      struct parse_events_error *err,
496e637d177SHe Kuang 				      struct list_head *head_config)
497bcd3279fSFrederic Weisbecker {
498bcd3279fSFrederic Weisbecker 	char evt_path[MAXPATHLEN];
499bcd3279fSFrederic Weisbecker 	struct dirent *evt_ent;
500bcd3279fSFrederic Weisbecker 	DIR *evt_dir;
50127bf90bfSJiri Olsa 	int ret = 0, found = 0;
502bcd3279fSFrederic Weisbecker 
503ebf294bfSArnaldo Carvalho de Melo 	snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name);
504bcd3279fSFrederic Weisbecker 	evt_dir = opendir(evt_path);
505bcd3279fSFrederic Weisbecker 	if (!evt_dir) {
506272ed29aSJiri Olsa 		tracepoint_error(err, errno, sys_name, evt_name);
50789812fc8SJiri Olsa 		return -1;
508bcd3279fSFrederic Weisbecker 	}
509bcd3279fSFrederic Weisbecker 
51089812fc8SJiri Olsa 	while (!ret && (evt_ent = readdir(evt_dir))) {
511bcd3279fSFrederic Weisbecker 		if (!strcmp(evt_ent->d_name, ".")
512bcd3279fSFrederic Weisbecker 		    || !strcmp(evt_ent->d_name, "..")
513bcd3279fSFrederic Weisbecker 		    || !strcmp(evt_ent->d_name, "enable")
514bcd3279fSFrederic Weisbecker 		    || !strcmp(evt_ent->d_name, "filter"))
515bcd3279fSFrederic Weisbecker 			continue;
516bcd3279fSFrederic Weisbecker 
51789812fc8SJiri Olsa 		if (!strglobmatch(evt_ent->d_name, evt_name))
518fb1d2edfSMasami Hiramatsu 			continue;
519fb1d2edfSMasami Hiramatsu 
52027bf90bfSJiri Olsa 		found++;
52127bf90bfSJiri Olsa 
522e637d177SHe Kuang 		ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name,
523272ed29aSJiri Olsa 				     err, head_config);
524bcd3279fSFrederic Weisbecker 	}
525bcd3279fSFrederic Weisbecker 
52627bf90bfSJiri Olsa 	if (!found) {
52727bf90bfSJiri Olsa 		tracepoint_error(err, ENOENT, sys_name, evt_name);
52827bf90bfSJiri Olsa 		ret = -1;
52927bf90bfSJiri Olsa 	}
53027bf90bfSJiri Olsa 
5310bd3f084SJiri Olsa 	closedir(evt_dir);
53289812fc8SJiri Olsa 	return ret;
533bcd3279fSFrederic Weisbecker }
534bcd3279fSFrederic Weisbecker 
535c5cd8ac0SDavid Ahern static int add_tracepoint_event(struct list_head *list, int *idx,
536e2f9f8eaSJiri Olsa 				char *sys_name, char *evt_name,
537272ed29aSJiri Olsa 				struct parse_events_error *err,
538e637d177SHe Kuang 				struct list_head *head_config)
539f35488f9SJiri Olsa {
540f35488f9SJiri Olsa 	return strpbrk(evt_name, "*?") ?
541e637d177SHe Kuang 	       add_tracepoint_multi_event(list, idx, sys_name, evt_name,
542272ed29aSJiri Olsa 					  err, head_config) :
543e637d177SHe Kuang 	       add_tracepoint(list, idx, sys_name, evt_name,
544272ed29aSJiri Olsa 			      err, head_config);
545f35488f9SJiri Olsa }
546f35488f9SJiri Olsa 
547c5cd8ac0SDavid Ahern static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
548e2f9f8eaSJiri Olsa 				    char *sys_name, char *evt_name,
549272ed29aSJiri Olsa 				    struct parse_events_error *err,
550e637d177SHe Kuang 				    struct list_head *head_config)
551f35488f9SJiri Olsa {
552f35488f9SJiri Olsa 	struct dirent *events_ent;
553f35488f9SJiri Olsa 	DIR *events_dir;
554f35488f9SJiri Olsa 	int ret = 0;
555f35488f9SJiri Olsa 
556f35488f9SJiri Olsa 	events_dir = opendir(tracing_events_path);
557f35488f9SJiri Olsa 	if (!events_dir) {
558272ed29aSJiri Olsa 		tracepoint_error(err, errno, sys_name, evt_name);
559f35488f9SJiri Olsa 		return -1;
560f35488f9SJiri Olsa 	}
561f35488f9SJiri Olsa 
562f35488f9SJiri Olsa 	while (!ret && (events_ent = readdir(events_dir))) {
563f35488f9SJiri Olsa 		if (!strcmp(events_ent->d_name, ".")
564f35488f9SJiri Olsa 		    || !strcmp(events_ent->d_name, "..")
565f35488f9SJiri Olsa 		    || !strcmp(events_ent->d_name, "enable")
566f35488f9SJiri Olsa 		    || !strcmp(events_ent->d_name, "header_event")
567f35488f9SJiri Olsa 		    || !strcmp(events_ent->d_name, "header_page"))
568f35488f9SJiri Olsa 			continue;
569f35488f9SJiri Olsa 
570f35488f9SJiri Olsa 		if (!strglobmatch(events_ent->d_name, sys_name))
571f35488f9SJiri Olsa 			continue;
572f35488f9SJiri Olsa 
573f35488f9SJiri Olsa 		ret = add_tracepoint_event(list, idx, events_ent->d_name,
574272ed29aSJiri Olsa 					   evt_name, err, head_config);
575f35488f9SJiri Olsa 	}
576f35488f9SJiri Olsa 
577f35488f9SJiri Olsa 	closedir(events_dir);
578f35488f9SJiri Olsa 	return ret;
579f35488f9SJiri Olsa }
580f35488f9SJiri Olsa 
5814edf30e3SWang Nan struct __add_bpf_event_param {
5824edf30e3SWang Nan 	struct parse_events_evlist *data;
5834edf30e3SWang Nan 	struct list_head *list;
5844edf30e3SWang Nan };
5854edf30e3SWang Nan 
5864edf30e3SWang Nan static int add_bpf_event(struct probe_trace_event *tev, int fd,
5874edf30e3SWang Nan 			 void *_param)
5884edf30e3SWang Nan {
5894edf30e3SWang Nan 	LIST_HEAD(new_evsels);
5904edf30e3SWang Nan 	struct __add_bpf_event_param *param = _param;
5914edf30e3SWang Nan 	struct parse_events_evlist *evlist = param->data;
5924edf30e3SWang Nan 	struct list_head *list = param->list;
5931f45b1d4SWang Nan 	struct perf_evsel *pos;
5944edf30e3SWang Nan 	int err;
5954edf30e3SWang Nan 
5964edf30e3SWang Nan 	pr_debug("add bpf event %s:%s and attach bpf program %d\n",
5974edf30e3SWang Nan 		 tev->group, tev->event, fd);
5984edf30e3SWang Nan 
5994edf30e3SWang Nan 	err = parse_events_add_tracepoint(&new_evsels, &evlist->idx, tev->group,
6004edf30e3SWang Nan 					  tev->event, evlist->error, NULL);
6014edf30e3SWang Nan 	if (err) {
6024edf30e3SWang Nan 		struct perf_evsel *evsel, *tmp;
6034edf30e3SWang Nan 
6044edf30e3SWang Nan 		pr_debug("Failed to add BPF event %s:%s\n",
6054edf30e3SWang Nan 			 tev->group, tev->event);
6064edf30e3SWang Nan 		list_for_each_entry_safe(evsel, tmp, &new_evsels, node) {
6074edf30e3SWang Nan 			list_del(&evsel->node);
6084edf30e3SWang Nan 			perf_evsel__delete(evsel);
6094edf30e3SWang Nan 		}
6104edf30e3SWang Nan 		return err;
6114edf30e3SWang Nan 	}
6124edf30e3SWang Nan 	pr_debug("adding %s:%s\n", tev->group, tev->event);
6134edf30e3SWang Nan 
6141f45b1d4SWang Nan 	list_for_each_entry(pos, &new_evsels, node) {
6151f45b1d4SWang Nan 		pr_debug("adding %s:%s to %p\n",
6161f45b1d4SWang Nan 			 tev->group, tev->event, pos);
6171f45b1d4SWang Nan 		pos->bpf_fd = fd;
6181f45b1d4SWang Nan 	}
6194edf30e3SWang Nan 	list_splice(&new_evsels, list);
6204edf30e3SWang Nan 	return 0;
6214edf30e3SWang Nan }
6224edf30e3SWang Nan 
62384c86ca1SWang Nan int parse_events_load_bpf_obj(struct parse_events_evlist *data,
62484c86ca1SWang Nan 			      struct list_head *list,
62584c86ca1SWang Nan 			      struct bpf_object *obj)
62684c86ca1SWang Nan {
62784c86ca1SWang Nan 	int err;
62884c86ca1SWang Nan 	char errbuf[BUFSIZ];
6294edf30e3SWang Nan 	struct __add_bpf_event_param param = {data, list};
630aa3abf30SWang Nan 	static bool registered_unprobe_atexit = false;
63184c86ca1SWang Nan 
63284c86ca1SWang Nan 	if (IS_ERR(obj) || !obj) {
63384c86ca1SWang Nan 		snprintf(errbuf, sizeof(errbuf),
63484c86ca1SWang Nan 			 "Internal error: load bpf obj with NULL");
63584c86ca1SWang Nan 		err = -EINVAL;
63684c86ca1SWang Nan 		goto errout;
63784c86ca1SWang Nan 	}
63884c86ca1SWang Nan 
63984c86ca1SWang Nan 	/*
640aa3abf30SWang Nan 	 * Register atexit handler before calling bpf__probe() so
641aa3abf30SWang Nan 	 * bpf__probe() don't need to unprobe probe points its already
642aa3abf30SWang Nan 	 * created when failure.
643aa3abf30SWang Nan 	 */
644aa3abf30SWang Nan 	if (!registered_unprobe_atexit) {
645aa3abf30SWang Nan 		atexit(bpf__clear);
646aa3abf30SWang Nan 		registered_unprobe_atexit = true;
647aa3abf30SWang Nan 	}
648aa3abf30SWang Nan 
649aa3abf30SWang Nan 	err = bpf__probe(obj);
650aa3abf30SWang Nan 	if (err) {
651aa3abf30SWang Nan 		bpf__strerror_probe(obj, err, errbuf, sizeof(errbuf));
652aa3abf30SWang Nan 		goto errout;
653aa3abf30SWang Nan 	}
654aa3abf30SWang Nan 
6551e5e3ee8SWang Nan 	err = bpf__load(obj);
6561e5e3ee8SWang Nan 	if (err) {
6571e5e3ee8SWang Nan 		bpf__strerror_load(obj, err, errbuf, sizeof(errbuf));
6581e5e3ee8SWang Nan 		goto errout;
6591e5e3ee8SWang Nan 	}
6601e5e3ee8SWang Nan 
6614edf30e3SWang Nan 	err = bpf__foreach_tev(obj, add_bpf_event, &param);
6624edf30e3SWang Nan 	if (err) {
6634edf30e3SWang Nan 		snprintf(errbuf, sizeof(errbuf),
6644edf30e3SWang Nan 			 "Attach events in BPF object failed");
6654edf30e3SWang Nan 		goto errout;
6664edf30e3SWang Nan 	}
6674edf30e3SWang Nan 
6684edf30e3SWang Nan 	return 0;
66984c86ca1SWang Nan errout:
67084c86ca1SWang Nan 	data->error->help = strdup("(add -v to see detail)");
67184c86ca1SWang Nan 	data->error->str = strdup(errbuf);
67284c86ca1SWang Nan 	return err;
67384c86ca1SWang Nan }
67484c86ca1SWang Nan 
675a34f3be7SWang Nan static int
676a34f3be7SWang Nan parse_events_config_bpf(struct parse_events_evlist *data,
677a34f3be7SWang Nan 			struct bpf_object *obj,
678a34f3be7SWang Nan 			struct list_head *head_config)
679a34f3be7SWang Nan {
680a34f3be7SWang Nan 	struct parse_events_term *term;
681a34f3be7SWang Nan 	int error_pos;
682a34f3be7SWang Nan 
683a34f3be7SWang Nan 	if (!head_config || list_empty(head_config))
684a34f3be7SWang Nan 		return 0;
685a34f3be7SWang Nan 
686a34f3be7SWang Nan 	list_for_each_entry(term, head_config, list) {
687a34f3be7SWang Nan 		char errbuf[BUFSIZ];
688a34f3be7SWang Nan 		int err;
689a34f3be7SWang Nan 
690a34f3be7SWang Nan 		if (term->type_term != PARSE_EVENTS__TERM_TYPE_USER) {
691a34f3be7SWang Nan 			snprintf(errbuf, sizeof(errbuf),
692a34f3be7SWang Nan 				 "Invalid config term for BPF object");
693a34f3be7SWang Nan 			errbuf[BUFSIZ - 1] = '\0';
694a34f3be7SWang Nan 
695a34f3be7SWang Nan 			data->error->idx = term->err_term;
696a34f3be7SWang Nan 			data->error->str = strdup(errbuf);
697a34f3be7SWang Nan 			return -EINVAL;
698a34f3be7SWang Nan 		}
699a34f3be7SWang Nan 
7007630b3e2SWang Nan 		err = bpf__config_obj(obj, term, data->evlist, &error_pos);
701a34f3be7SWang Nan 		if (err) {
7027630b3e2SWang Nan 			bpf__strerror_config_obj(obj, term, data->evlist,
703a34f3be7SWang Nan 						 &error_pos, err, errbuf,
704a34f3be7SWang Nan 						 sizeof(errbuf));
705a34f3be7SWang Nan 			data->error->help = strdup(
7067630b3e2SWang Nan "Hint:\tValid config terms:\n"
707*e571e029SWang Nan "     \tmap:[<arraymap>].value<indices>=[value]\n"
708*e571e029SWang Nan "     \tmap:[<eventmap>].event<indices>=[event]\n"
7097630b3e2SWang Nan "\n"
710*e571e029SWang Nan "     \twhere <indices> is something like [0,3...5] or [all]\n"
711a34f3be7SWang Nan "     \t(add -v to see detail)");
712a34f3be7SWang Nan 			data->error->str = strdup(errbuf);
713a34f3be7SWang Nan 			if (err == -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE)
714a34f3be7SWang Nan 				data->error->idx = term->err_val;
715a34f3be7SWang Nan 			else
716a34f3be7SWang Nan 				data->error->idx = term->err_term + error_pos;
717a34f3be7SWang Nan 			return err;
718a34f3be7SWang Nan 		}
719a34f3be7SWang Nan 	}
720a34f3be7SWang Nan 	return 0;
721a34f3be7SWang Nan }
722a34f3be7SWang Nan 
72384c86ca1SWang Nan int parse_events_load_bpf(struct parse_events_evlist *data,
72484c86ca1SWang Nan 			  struct list_head *list,
725d509db04SWang Nan 			  char *bpf_file_name,
726a34f3be7SWang Nan 			  bool source,
727a34f3be7SWang Nan 			  struct list_head *head_config)
72884c86ca1SWang Nan {
72984c86ca1SWang Nan 	struct bpf_object *obj;
730a34f3be7SWang Nan 	int err;
73184c86ca1SWang Nan 
732d509db04SWang Nan 	obj = bpf__prepare_load(bpf_file_name, source);
7336371ca3bSWang Nan 	if (IS_ERR(obj)) {
73484c86ca1SWang Nan 		char errbuf[BUFSIZ];
73584c86ca1SWang Nan 
7366371ca3bSWang Nan 		err = PTR_ERR(obj);
73784c86ca1SWang Nan 
73884c86ca1SWang Nan 		if (err == -ENOTSUP)
73984c86ca1SWang Nan 			snprintf(errbuf, sizeof(errbuf),
74084c86ca1SWang Nan 				 "BPF support is not compiled");
74184c86ca1SWang Nan 		else
742d3e0ce39SWang Nan 			bpf__strerror_prepare_load(bpf_file_name,
743d3e0ce39SWang Nan 						   source,
744d3e0ce39SWang Nan 						   -err, errbuf,
745d3e0ce39SWang Nan 						   sizeof(errbuf));
74684c86ca1SWang Nan 
74784c86ca1SWang Nan 		data->error->help = strdup("(add -v to see detail)");
74884c86ca1SWang Nan 		data->error->str = strdup(errbuf);
74984c86ca1SWang Nan 		return err;
75084c86ca1SWang Nan 	}
75184c86ca1SWang Nan 
752a34f3be7SWang Nan 	err = parse_events_load_bpf_obj(data, list, obj);
753a34f3be7SWang Nan 	if (err)
754a34f3be7SWang Nan 		return err;
755a34f3be7SWang Nan 	return parse_events_config_bpf(data, obj, head_config);
75684c86ca1SWang Nan }
75784c86ca1SWang Nan 
75889812fc8SJiri Olsa static int
75989812fc8SJiri Olsa parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
7601b290d67SFrederic Weisbecker {
7611b290d67SFrederic Weisbecker 	int i;
7621b290d67SFrederic Weisbecker 
7631b290d67SFrederic Weisbecker 	for (i = 0; i < 3; i++) {
76489812fc8SJiri Olsa 		if (!type || !type[i])
7651b290d67SFrederic Weisbecker 			break;
7661b290d67SFrederic Weisbecker 
7677582732fSJiri Olsa #define CHECK_SET_TYPE(bit)		\
7687582732fSJiri Olsa do {					\
7697582732fSJiri Olsa 	if (attr->bp_type & bit)	\
7707582732fSJiri Olsa 		return -EINVAL;		\
7717582732fSJiri Olsa 	else				\
7727582732fSJiri Olsa 		attr->bp_type |= bit;	\
7737582732fSJiri Olsa } while (0)
7747582732fSJiri Olsa 
7751b290d67SFrederic Weisbecker 		switch (type[i]) {
7761b290d67SFrederic Weisbecker 		case 'r':
7777582732fSJiri Olsa 			CHECK_SET_TYPE(HW_BREAKPOINT_R);
7781b290d67SFrederic Weisbecker 			break;
7791b290d67SFrederic Weisbecker 		case 'w':
7807582732fSJiri Olsa 			CHECK_SET_TYPE(HW_BREAKPOINT_W);
7811b290d67SFrederic Weisbecker 			break;
7821b290d67SFrederic Weisbecker 		case 'x':
7837582732fSJiri Olsa 			CHECK_SET_TYPE(HW_BREAKPOINT_X);
7841b290d67SFrederic Weisbecker 			break;
7851b290d67SFrederic Weisbecker 		default:
78689812fc8SJiri Olsa 			return -EINVAL;
7871b290d67SFrederic Weisbecker 		}
7881b290d67SFrederic Weisbecker 	}
78989812fc8SJiri Olsa 
7907582732fSJiri Olsa #undef CHECK_SET_TYPE
7917582732fSJiri Olsa 
7921b290d67SFrederic Weisbecker 	if (!attr->bp_type) /* Default */
7931b290d67SFrederic Weisbecker 		attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
7941b290d67SFrederic Weisbecker 
79589812fc8SJiri Olsa 	return 0;
7961b290d67SFrederic Weisbecker }
7971b290d67SFrederic Weisbecker 
798c5cd8ac0SDavid Ahern int parse_events_add_breakpoint(struct list_head *list, int *idx,
7993741eb9fSJacob Shin 				void *ptr, char *type, u64 len)
8001b290d67SFrederic Weisbecker {
80189812fc8SJiri Olsa 	struct perf_event_attr attr;
8021b290d67SFrederic Weisbecker 
80389812fc8SJiri Olsa 	memset(&attr, 0, sizeof(attr));
8049fafd98fSJiri Olsa 	attr.bp_addr = (unsigned long) ptr;
8051b290d67SFrederic Weisbecker 
80689812fc8SJiri Olsa 	if (parse_breakpoint_type(type, &attr))
80789812fc8SJiri Olsa 		return -EINVAL;
8081b290d67SFrederic Weisbecker 
8093741eb9fSJacob Shin 	/* Provide some defaults if len is not specified */
8103741eb9fSJacob Shin 	if (!len) {
81189812fc8SJiri Olsa 		if (attr.bp_type == HW_BREAKPOINT_X)
8123741eb9fSJacob Shin 			len = sizeof(long);
813aa59a485SFrederic Weisbecker 		else
8143741eb9fSJacob Shin 			len = HW_BREAKPOINT_LEN_4;
8153741eb9fSJacob Shin 	}
8163741eb9fSJacob Shin 
8173741eb9fSJacob Shin 	attr.bp_len = len;
818aa59a485SFrederic Weisbecker 
81989812fc8SJiri Olsa 	attr.type = PERF_TYPE_BREAKPOINT;
8204a841d65SJovi Zhang 	attr.sample_period = 1;
8211b290d67SFrederic Weisbecker 
822930a2e29SJiri Olsa 	return add_event(list, idx, &attr, NULL, NULL);
8231b290d67SFrederic Weisbecker }
8241b290d67SFrederic Weisbecker 
8253b0e371cSJiri Olsa static int check_type_val(struct parse_events_term *term,
8263b0e371cSJiri Olsa 			  struct parse_events_error *err,
8273b0e371cSJiri Olsa 			  int type)
8283b0e371cSJiri Olsa {
8293b0e371cSJiri Olsa 	if (type == term->type_val)
8303b0e371cSJiri Olsa 		return 0;
8313b0e371cSJiri Olsa 
8323b0e371cSJiri Olsa 	if (err) {
8333b0e371cSJiri Olsa 		err->idx = term->err_val;
8343b0e371cSJiri Olsa 		if (type == PARSE_EVENTS__TERM_TYPE_NUM)
8353b0e371cSJiri Olsa 			err->str = strdup("expected numeric value");
8363b0e371cSJiri Olsa 		else
8373b0e371cSJiri Olsa 			err->str = strdup("expected string value");
8383b0e371cSJiri Olsa 	}
8393b0e371cSJiri Olsa 	return -EINVAL;
8403b0e371cSJiri Olsa }
8413b0e371cSJiri Olsa 
84217cb5f84SWang Nan /*
84317cb5f84SWang Nan  * Update according to parse-events.l
84417cb5f84SWang Nan  */
84517cb5f84SWang Nan static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = {
84617cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_USER]			= "<sysfs term>",
84717cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_CONFIG]		= "config",
84817cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_CONFIG1]		= "config1",
84917cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_CONFIG2]		= "config2",
85017cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_NAME]			= "name",
85117cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD]		= "period",
85217cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ]		= "freq",
85317cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE]	= "branch_type",
85417cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_TIME]			= "time",
85517cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_CALLGRAPH]		= "call-graph",
85617cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_STACKSIZE]		= "stack-size",
85717cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_NOINHERIT]		= "no-inherit",
85817cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_INHERIT]		= "inherit",
85917cb5f84SWang Nan };
86017cb5f84SWang Nan 
8611669e509SWang Nan static bool config_term_shrinked;
8621669e509SWang Nan 
8631669e509SWang Nan static bool
8641669e509SWang Nan config_term_avail(int term_type, struct parse_events_error *err)
8651669e509SWang Nan {
8661669e509SWang Nan 	if (term_type < 0 || term_type >= __PARSE_EVENTS__TERM_TYPE_NR) {
8671669e509SWang Nan 		err->str = strdup("Invalid term_type");
8681669e509SWang Nan 		return false;
8691669e509SWang Nan 	}
8701669e509SWang Nan 	if (!config_term_shrinked)
8711669e509SWang Nan 		return true;
8721669e509SWang Nan 
8731669e509SWang Nan 	switch (term_type) {
8741669e509SWang Nan 	case PARSE_EVENTS__TERM_TYPE_CONFIG:
8751669e509SWang Nan 	case PARSE_EVENTS__TERM_TYPE_CONFIG1:
8761669e509SWang Nan 	case PARSE_EVENTS__TERM_TYPE_CONFIG2:
8771669e509SWang Nan 	case PARSE_EVENTS__TERM_TYPE_NAME:
8781669e509SWang Nan 		return true;
8791669e509SWang Nan 	default:
8801669e509SWang Nan 		if (!err)
8811669e509SWang Nan 			return false;
8821669e509SWang Nan 
8831669e509SWang Nan 		/* term_type is validated so indexing is safe */
8841669e509SWang Nan 		if (asprintf(&err->str, "'%s' is not usable in 'perf stat'",
8851669e509SWang Nan 			     config_term_names[term_type]) < 0)
8861669e509SWang Nan 			err->str = NULL;
8871669e509SWang Nan 		return false;
8881669e509SWang Nan 	}
8891669e509SWang Nan }
8901669e509SWang Nan 
8911669e509SWang Nan void parse_events__shrink_config_terms(void)
8921669e509SWang Nan {
8931669e509SWang Nan 	config_term_shrinked = true;
8941669e509SWang Nan }
8951669e509SWang Nan 
8960b8891a8SHe Kuang static int config_term_common(struct perf_event_attr *attr,
8973b0e371cSJiri Olsa 			      struct parse_events_term *term,
8983b0e371cSJiri Olsa 			      struct parse_events_error *err)
8998f707d84SJiri Olsa {
90016fa7e82SJiri Olsa #define CHECK_TYPE_VAL(type)						   \
90116fa7e82SJiri Olsa do {									   \
9023b0e371cSJiri Olsa 	if (check_type_val(term, err, PARSE_EVENTS__TERM_TYPE_ ## type)) \
90316fa7e82SJiri Olsa 		return -EINVAL;						   \
90416fa7e82SJiri Olsa } while (0)
90516fa7e82SJiri Olsa 
90616fa7e82SJiri Olsa 	switch (term->type_term) {
9078f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_CONFIG:
90816fa7e82SJiri Olsa 		CHECK_TYPE_VAL(NUM);
9098f707d84SJiri Olsa 		attr->config = term->val.num;
9108f707d84SJiri Olsa 		break;
9118f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_CONFIG1:
91216fa7e82SJiri Olsa 		CHECK_TYPE_VAL(NUM);
9138f707d84SJiri Olsa 		attr->config1 = term->val.num;
9148f707d84SJiri Olsa 		break;
9158f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_CONFIG2:
91616fa7e82SJiri Olsa 		CHECK_TYPE_VAL(NUM);
9178f707d84SJiri Olsa 		attr->config2 = term->val.num;
9188f707d84SJiri Olsa 		break;
9198f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
92016fa7e82SJiri Olsa 		CHECK_TYPE_VAL(NUM);
9218f707d84SJiri Olsa 		break;
92209af2a55SNamhyung Kim 	case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ:
92309af2a55SNamhyung Kim 		CHECK_TYPE_VAL(NUM);
92409af2a55SNamhyung Kim 		break;
9258f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE:
9268f707d84SJiri Olsa 		/*
9278f707d84SJiri Olsa 		 * TODO uncomment when the field is available
9288f707d84SJiri Olsa 		 * attr->branch_sample_type = term->val.num;
9298f707d84SJiri Olsa 		 */
9308f707d84SJiri Olsa 		break;
93132067712SKan Liang 	case PARSE_EVENTS__TERM_TYPE_TIME:
93232067712SKan Liang 		CHECK_TYPE_VAL(NUM);
93332067712SKan Liang 		if (term->val.num > 1) {
93432067712SKan Liang 			err->str = strdup("expected 0 or 1");
93532067712SKan Liang 			err->idx = term->err_val;
93632067712SKan Liang 			return -EINVAL;
93732067712SKan Liang 		}
93832067712SKan Liang 		break;
939d457c963SKan Liang 	case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
940d457c963SKan Liang 		CHECK_TYPE_VAL(STR);
941d457c963SKan Liang 		break;
942d457c963SKan Liang 	case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
943d457c963SKan Liang 		CHECK_TYPE_VAL(NUM);
944d457c963SKan Liang 		break;
945374ce938SWang Nan 	case PARSE_EVENTS__TERM_TYPE_INHERIT:
946374ce938SWang Nan 		CHECK_TYPE_VAL(NUM);
947374ce938SWang Nan 		break;
948374ce938SWang Nan 	case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
949374ce938SWang Nan 		CHECK_TYPE_VAL(NUM);
950374ce938SWang Nan 		break;
9516b5fc39bSJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_NAME:
9526b5fc39bSJiri Olsa 		CHECK_TYPE_VAL(STR);
9536b5fc39bSJiri Olsa 		break;
9548f707d84SJiri Olsa 	default:
955ffeb883eSHe Kuang 		err->str = strdup("unknown term");
956ffeb883eSHe Kuang 		err->idx = term->err_term;
957ffeb883eSHe Kuang 		err->help = parse_events_formats_error_string(NULL);
9588f707d84SJiri Olsa 		return -EINVAL;
9598f707d84SJiri Olsa 	}
96016fa7e82SJiri Olsa 
9611669e509SWang Nan 	/*
9621669e509SWang Nan 	 * Check term availbility after basic checking so
9631669e509SWang Nan 	 * PARSE_EVENTS__TERM_TYPE_USER can be found and filtered.
9641669e509SWang Nan 	 *
9651669e509SWang Nan 	 * If check availbility at the entry of this function,
9661669e509SWang Nan 	 * user will see "'<sysfs term>' is not usable in 'perf stat'"
9671669e509SWang Nan 	 * if an invalid config term is provided for legacy events
9681669e509SWang Nan 	 * (for example, instructions/badterm/...), which is confusing.
9691669e509SWang Nan 	 */
9701669e509SWang Nan 	if (!config_term_avail(term->type_term, err))
9711669e509SWang Nan 		return -EINVAL;
9728f707d84SJiri Olsa 	return 0;
97316fa7e82SJiri Olsa #undef CHECK_TYPE_VAL
9748f707d84SJiri Olsa }
9758f707d84SJiri Olsa 
9760b8891a8SHe Kuang static int config_term_pmu(struct perf_event_attr *attr,
9770b8891a8SHe Kuang 			   struct parse_events_term *term,
9780b8891a8SHe Kuang 			   struct parse_events_error *err)
9790b8891a8SHe Kuang {
9800b8891a8SHe Kuang 	if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER)
9810b8891a8SHe Kuang 		/*
9820b8891a8SHe Kuang 		 * Always succeed for sysfs terms, as we dont know
9830b8891a8SHe Kuang 		 * at this point what type they need to have.
9840b8891a8SHe Kuang 		 */
9850b8891a8SHe Kuang 		return 0;
9860b8891a8SHe Kuang 	else
9870b8891a8SHe Kuang 		return config_term_common(attr, term, err);
9880b8891a8SHe Kuang }
9890b8891a8SHe Kuang 
990e637d177SHe Kuang static int config_term_tracepoint(struct perf_event_attr *attr,
991e637d177SHe Kuang 				  struct parse_events_term *term,
992e637d177SHe Kuang 				  struct parse_events_error *err)
993e637d177SHe Kuang {
994e637d177SHe Kuang 	switch (term->type_term) {
995e637d177SHe Kuang 	case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
996e637d177SHe Kuang 	case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
997374ce938SWang Nan 	case PARSE_EVENTS__TERM_TYPE_INHERIT:
998374ce938SWang Nan 	case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
999e637d177SHe Kuang 		return config_term_common(attr, term, err);
1000e637d177SHe Kuang 	default:
1001e637d177SHe Kuang 		if (err) {
1002e637d177SHe Kuang 			err->idx = term->err_term;
1003e637d177SHe Kuang 			err->str = strdup("unknown term");
1004e637d177SHe Kuang 			err->help = strdup("valid terms: call-graph,stack-size\n");
1005e637d177SHe Kuang 		}
1006e637d177SHe Kuang 		return -EINVAL;
1007e637d177SHe Kuang 	}
1008e637d177SHe Kuang 
1009e637d177SHe Kuang 	return 0;
1010e637d177SHe Kuang }
1011e637d177SHe Kuang 
10128f707d84SJiri Olsa static int config_attr(struct perf_event_attr *attr,
10133b0e371cSJiri Olsa 		       struct list_head *head,
10140b8891a8SHe Kuang 		       struct parse_events_error *err,
10150b8891a8SHe Kuang 		       config_term_func_t config_term)
10168f707d84SJiri Olsa {
10176cee6cd3SArnaldo Carvalho de Melo 	struct parse_events_term *term;
10188f707d84SJiri Olsa 
10198f707d84SJiri Olsa 	list_for_each_entry(term, head, list)
10203b0e371cSJiri Olsa 		if (config_term(attr, term, err))
10218f707d84SJiri Olsa 			return -EINVAL;
10228f707d84SJiri Olsa 
10238f707d84SJiri Olsa 	return 0;
10248f707d84SJiri Olsa }
10258f707d84SJiri Olsa 
1026930a2e29SJiri Olsa static int get_config_terms(struct list_head *head_config,
1027930a2e29SJiri Olsa 			    struct list_head *head_terms __maybe_unused)
1028930a2e29SJiri Olsa {
1029930a2e29SJiri Olsa #define ADD_CONFIG_TERM(__type, __name, __val)			\
1030930a2e29SJiri Olsa do {								\
1031930a2e29SJiri Olsa 	struct perf_evsel_config_term *__t;			\
1032930a2e29SJiri Olsa 								\
1033930a2e29SJiri Olsa 	__t = zalloc(sizeof(*__t));				\
1034930a2e29SJiri Olsa 	if (!__t)						\
1035930a2e29SJiri Olsa 		return -ENOMEM;					\
1036930a2e29SJiri Olsa 								\
1037930a2e29SJiri Olsa 	INIT_LIST_HEAD(&__t->list);				\
1038930a2e29SJiri Olsa 	__t->type       = PERF_EVSEL__CONFIG_TERM_ ## __type;	\
1039930a2e29SJiri Olsa 	__t->val.__name = __val;				\
1040930a2e29SJiri Olsa 	list_add_tail(&__t->list, head_terms);			\
1041930a2e29SJiri Olsa } while (0)
1042930a2e29SJiri Olsa 
1043930a2e29SJiri Olsa 	struct parse_events_term *term;
1044930a2e29SJiri Olsa 
1045930a2e29SJiri Olsa 	list_for_each_entry(term, head_config, list) {
1046930a2e29SJiri Olsa 		switch (term->type_term) {
1047ee4c7588SJiri Olsa 		case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
1048ee4c7588SJiri Olsa 			ADD_CONFIG_TERM(PERIOD, period, term->val.num);
104932067712SKan Liang 			break;
105009af2a55SNamhyung Kim 		case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ:
105109af2a55SNamhyung Kim 			ADD_CONFIG_TERM(FREQ, freq, term->val.num);
105209af2a55SNamhyung Kim 			break;
105332067712SKan Liang 		case PARSE_EVENTS__TERM_TYPE_TIME:
105432067712SKan Liang 			ADD_CONFIG_TERM(TIME, time, term->val.num);
105532067712SKan Liang 			break;
1056d457c963SKan Liang 		case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
1057d457c963SKan Liang 			ADD_CONFIG_TERM(CALLGRAPH, callgraph, term->val.str);
1058d457c963SKan Liang 			break;
1059d457c963SKan Liang 		case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
1060d457c963SKan Liang 			ADD_CONFIG_TERM(STACK_USER, stack_user, term->val.num);
1061d457c963SKan Liang 			break;
1062374ce938SWang Nan 		case PARSE_EVENTS__TERM_TYPE_INHERIT:
1063374ce938SWang Nan 			ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 1 : 0);
1064374ce938SWang Nan 			break;
1065374ce938SWang Nan 		case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
1066374ce938SWang Nan 			ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 0 : 1);
1067374ce938SWang Nan 			break;
1068930a2e29SJiri Olsa 		default:
1069930a2e29SJiri Olsa 			break;
1070930a2e29SJiri Olsa 		}
1071930a2e29SJiri Olsa 	}
1072930a2e29SJiri Olsa #undef ADD_EVSEL_CONFIG
1073930a2e29SJiri Olsa 	return 0;
1074930a2e29SJiri Olsa }
1075930a2e29SJiri Olsa 
1076e637d177SHe Kuang int parse_events_add_tracepoint(struct list_head *list, int *idx,
1077e637d177SHe Kuang 				char *sys, char *event,
1078272ed29aSJiri Olsa 				struct parse_events_error *err,
1079e637d177SHe Kuang 				struct list_head *head_config)
1080e637d177SHe Kuang {
1081e637d177SHe Kuang 	if (head_config) {
1082e637d177SHe Kuang 		struct perf_event_attr attr;
1083e637d177SHe Kuang 
1084272ed29aSJiri Olsa 		if (config_attr(&attr, head_config, err,
1085e637d177SHe Kuang 				config_term_tracepoint))
1086e637d177SHe Kuang 			return -EINVAL;
1087e637d177SHe Kuang 	}
1088e637d177SHe Kuang 
1089e637d177SHe Kuang 	if (strpbrk(sys, "*?"))
1090e637d177SHe Kuang 		return add_tracepoint_multi_sys(list, idx, sys, event,
1091272ed29aSJiri Olsa 						err, head_config);
1092e637d177SHe Kuang 	else
1093e637d177SHe Kuang 		return add_tracepoint_event(list, idx, sys, event,
1094272ed29aSJiri Olsa 					    err, head_config);
1095e637d177SHe Kuang }
1096e637d177SHe Kuang 
109787d650beSJiri Olsa int parse_events_add_numeric(struct parse_events_evlist *data,
109887d650beSJiri Olsa 			     struct list_head *list,
1099b527bab5SRobert Richter 			     u32 type, u64 config,
11008f707d84SJiri Olsa 			     struct list_head *head_config)
110174d5b588SJaswinder Singh Rajput {
110289812fc8SJiri Olsa 	struct perf_event_attr attr;
1103930a2e29SJiri Olsa 	LIST_HEAD(config_terms);
110474d5b588SJaswinder Singh Rajput 
110589812fc8SJiri Olsa 	memset(&attr, 0, sizeof(attr));
110689812fc8SJiri Olsa 	attr.type = type;
110789812fc8SJiri Olsa 	attr.config = config;
11088f707d84SJiri Olsa 
1109930a2e29SJiri Olsa 	if (head_config) {
11100b8891a8SHe Kuang 		if (config_attr(&attr, head_config, data->error,
11110b8891a8SHe Kuang 				config_term_common))
11128f707d84SJiri Olsa 			return -EINVAL;
11138f707d84SJiri Olsa 
1114930a2e29SJiri Olsa 		if (get_config_terms(head_config, &config_terms))
1115930a2e29SJiri Olsa 			return -ENOMEM;
1116930a2e29SJiri Olsa 	}
1117930a2e29SJiri Olsa 
111810bf358aSWang Nan 	return add_event(list, &data->idx, &attr,
111910bf358aSWang Nan 			 get_config_name(head_config), &config_terms);
1120b908debdSIngo Molnar }
1121b908debdSIngo Molnar 
112236adec85SJiri Olsa int parse_events_add_pmu(struct parse_events_evlist *data,
112336adec85SJiri Olsa 			 struct list_head *list, char *name,
112436adec85SJiri Olsa 			 struct list_head *head_config)
11255f537a26SJiri Olsa {
11265f537a26SJiri Olsa 	struct perf_event_attr attr;
112746441bdcSMatt Fleming 	struct perf_pmu_info info;
11285f537a26SJiri Olsa 	struct perf_pmu *pmu;
1129410136f5SStephane Eranian 	struct perf_evsel *evsel;
1130930a2e29SJiri Olsa 	LIST_HEAD(config_terms);
11315f537a26SJiri Olsa 
11325f537a26SJiri Olsa 	pmu = perf_pmu__find(name);
11335f537a26SJiri Olsa 	if (!pmu)
11345f537a26SJiri Olsa 		return -EINVAL;
11355f537a26SJiri Olsa 
1136dc0a6202SAdrian Hunter 	if (pmu->default_config) {
1137dc0a6202SAdrian Hunter 		memcpy(&attr, pmu->default_config,
1138dc0a6202SAdrian Hunter 		       sizeof(struct perf_event_attr));
1139dc0a6202SAdrian Hunter 	} else {
11405f537a26SJiri Olsa 		memset(&attr, 0, sizeof(attr));
1141dc0a6202SAdrian Hunter 	}
11425f537a26SJiri Olsa 
1143ad962273SAdrian Hunter 	if (!head_config) {
1144ad962273SAdrian Hunter 		attr.type = pmu->type;
1145930a2e29SJiri Olsa 		evsel = __add_event(list, &data->idx, &attr, NULL, pmu->cpus, NULL);
1146ad962273SAdrian Hunter 		return evsel ? 0 : -ENOMEM;
1147ad962273SAdrian Hunter 	}
1148ad962273SAdrian Hunter 
114946441bdcSMatt Fleming 	if (perf_pmu__check_alias(pmu, head_config, &info))
1150a6146d50SZheng Yan 		return -EINVAL;
1151a6146d50SZheng Yan 
11525f537a26SJiri Olsa 	/*
11535f537a26SJiri Olsa 	 * Configure hardcoded terms first, no need to check
11545f537a26SJiri Olsa 	 * return value when called with fail == 0 ;)
11555f537a26SJiri Olsa 	 */
11560b8891a8SHe Kuang 	if (config_attr(&attr, head_config, data->error, config_term_pmu))
1157c056ba6aSJiri Olsa 		return -EINVAL;
11585f537a26SJiri Olsa 
1159930a2e29SJiri Olsa 	if (get_config_terms(head_config, &config_terms))
1160930a2e29SJiri Olsa 		return -ENOMEM;
1161930a2e29SJiri Olsa 
1162e64b020bSJiri Olsa 	if (perf_pmu__config(pmu, &attr, head_config, data->error))
11635f537a26SJiri Olsa 		return -EINVAL;
11645f537a26SJiri Olsa 
116536adec85SJiri Olsa 	evsel = __add_event(list, &data->idx, &attr,
1166e814fdddSWang Nan 			    get_config_name(head_config), pmu->cpus,
1167930a2e29SJiri Olsa 			    &config_terms);
1168410136f5SStephane Eranian 	if (evsel) {
116946441bdcSMatt Fleming 		evsel->unit = info.unit;
117046441bdcSMatt Fleming 		evsel->scale = info.scale;
1171044330c1SMatt Fleming 		evsel->per_pkg = info.per_pkg;
11721d9e446bSJiri Olsa 		evsel->snapshot = info.snapshot;
1173410136f5SStephane Eranian 	}
1174410136f5SStephane Eranian 
1175410136f5SStephane Eranian 	return evsel ? 0 : -ENOMEM;
11765f537a26SJiri Olsa }
11775f537a26SJiri Olsa 
11786a4bb04cSJiri Olsa int parse_events__modifier_group(struct list_head *list,
11796a4bb04cSJiri Olsa 				 char *event_mod)
118089efb029SJiri Olsa {
11816a4bb04cSJiri Olsa 	return parse_events__modifier_event(list, event_mod, true);
11826a4bb04cSJiri Olsa }
11836a4bb04cSJiri Olsa 
118463dab225SArnaldo Carvalho de Melo void parse_events__set_leader(char *name, struct list_head *list)
11856a4bb04cSJiri Olsa {
11866a4bb04cSJiri Olsa 	struct perf_evsel *leader;
11876a4bb04cSJiri Olsa 
1188854f7363SWang Nan 	if (list_empty(list)) {
1189854f7363SWang Nan 		WARN_ONCE(true, "WARNING: failed to set leader: empty list");
1190854f7363SWang Nan 		return;
1191854f7363SWang Nan 	}
1192854f7363SWang Nan 
119363dab225SArnaldo Carvalho de Melo 	__perf_evlist__set_leader(list);
119463dab225SArnaldo Carvalho de Melo 	leader = list_entry(list->next, struct perf_evsel, node);
11956a4bb04cSJiri Olsa 	leader->group_name = name ? strdup(name) : NULL;
119689efb029SJiri Olsa }
119789efb029SJiri Olsa 
1198c5cd8ac0SDavid Ahern /* list_event is assumed to point to malloc'ed memory */
11995d7be90eSJiri Olsa void parse_events_update_lists(struct list_head *list_event,
12005d7be90eSJiri Olsa 			       struct list_head *list_all)
12015d7be90eSJiri Olsa {
12025d7be90eSJiri Olsa 	/*
12035d7be90eSJiri Olsa 	 * Called for single event definition. Update the
120489efb029SJiri Olsa 	 * 'all event' list, and reinit the 'single event'
12055d7be90eSJiri Olsa 	 * list, for next event definition.
12065d7be90eSJiri Olsa 	 */
12075d7be90eSJiri Olsa 	list_splice_tail(list_event, list_all);
1208b847cbdcSJiri Olsa 	free(list_event);
12095d7be90eSJiri Olsa }
12105d7be90eSJiri Olsa 
1211f5b1135bSJiri Olsa struct event_modifier {
1212f5b1135bSJiri Olsa 	int eu;
1213f5b1135bSJiri Olsa 	int ek;
1214f5b1135bSJiri Olsa 	int eh;
1215f5b1135bSJiri Olsa 	int eH;
1216f5b1135bSJiri Olsa 	int eG;
1217a1e12da4SJiri Olsa 	int eI;
1218f5b1135bSJiri Olsa 	int precise;
12197f94af7aSJiri Olsa 	int precise_max;
1220f5b1135bSJiri Olsa 	int exclude_GH;
12213c176311SJiri Olsa 	int sample_read;
1222e9a7c414SMichael Ellerman 	int pinned;
1223f5b1135bSJiri Olsa };
122461c45981SPaul Mackerras 
1225f5b1135bSJiri Olsa static int get_event_modifier(struct event_modifier *mod, char *str,
1226f5b1135bSJiri Olsa 			       struct perf_evsel *evsel)
1227f5b1135bSJiri Olsa {
1228f5b1135bSJiri Olsa 	int eu = evsel ? evsel->attr.exclude_user : 0;
1229f5b1135bSJiri Olsa 	int ek = evsel ? evsel->attr.exclude_kernel : 0;
1230f5b1135bSJiri Olsa 	int eh = evsel ? evsel->attr.exclude_hv : 0;
1231f5b1135bSJiri Olsa 	int eH = evsel ? evsel->attr.exclude_host : 0;
1232f5b1135bSJiri Olsa 	int eG = evsel ? evsel->attr.exclude_guest : 0;
1233a1e12da4SJiri Olsa 	int eI = evsel ? evsel->attr.exclude_idle : 0;
1234f5b1135bSJiri Olsa 	int precise = evsel ? evsel->attr.precise_ip : 0;
12357f94af7aSJiri Olsa 	int precise_max = 0;
12363c176311SJiri Olsa 	int sample_read = 0;
1237e9a7c414SMichael Ellerman 	int pinned = evsel ? evsel->attr.pinned : 0;
1238f5b1135bSJiri Olsa 
1239f5b1135bSJiri Olsa 	int exclude = eu | ek | eh;
1240f5b1135bSJiri Olsa 	int exclude_GH = evsel ? evsel->exclude_GH : 0;
1241f5b1135bSJiri Olsa 
1242f5b1135bSJiri Olsa 	memset(mod, 0, sizeof(*mod));
1243ceb53fbfSIngo Molnar 
124461c45981SPaul Mackerras 	while (*str) {
1245ab608344SPeter Zijlstra 		if (*str == 'u') {
1246ab608344SPeter Zijlstra 			if (!exclude)
1247ab608344SPeter Zijlstra 				exclude = eu = ek = eh = 1;
124861c45981SPaul Mackerras 			eu = 0;
1249ab608344SPeter Zijlstra 		} else if (*str == 'k') {
1250ab608344SPeter Zijlstra 			if (!exclude)
1251ab608344SPeter Zijlstra 				exclude = eu = ek = eh = 1;
125261c45981SPaul Mackerras 			ek = 0;
1253ab608344SPeter Zijlstra 		} else if (*str == 'h') {
1254ab608344SPeter Zijlstra 			if (!exclude)
1255ab608344SPeter Zijlstra 				exclude = eu = ek = eh = 1;
125661c45981SPaul Mackerras 			eh = 0;
125799320cc8SJoerg Roedel 		} else if (*str == 'G') {
125899320cc8SJoerg Roedel 			if (!exclude_GH)
125999320cc8SJoerg Roedel 				exclude_GH = eG = eH = 1;
126099320cc8SJoerg Roedel 			eG = 0;
126199320cc8SJoerg Roedel 		} else if (*str == 'H') {
126299320cc8SJoerg Roedel 			if (!exclude_GH)
126399320cc8SJoerg Roedel 				exclude_GH = eG = eH = 1;
126499320cc8SJoerg Roedel 			eH = 0;
1265a1e12da4SJiri Olsa 		} else if (*str == 'I') {
1266a1e12da4SJiri Olsa 			eI = 1;
1267ab608344SPeter Zijlstra 		} else if (*str == 'p') {
1268ab608344SPeter Zijlstra 			precise++;
12691342798cSDavid Ahern 			/* use of precise requires exclude_guest */
12701342798cSDavid Ahern 			if (!exclude_GH)
12711342798cSDavid Ahern 				eG = 1;
12727f94af7aSJiri Olsa 		} else if (*str == 'P') {
12737f94af7aSJiri Olsa 			precise_max = 1;
12743c176311SJiri Olsa 		} else if (*str == 'S') {
12753c176311SJiri Olsa 			sample_read = 1;
1276e9a7c414SMichael Ellerman 		} else if (*str == 'D') {
1277e9a7c414SMichael Ellerman 			pinned = 1;
1278ab608344SPeter Zijlstra 		} else
127961c45981SPaul Mackerras 			break;
1280ab608344SPeter Zijlstra 
128161c45981SPaul Mackerras 		++str;
128261c45981SPaul Mackerras 	}
128374d5b588SJaswinder Singh Rajput 
128486470930SIngo Molnar 	/*
128589812fc8SJiri Olsa 	 * precise ip:
128689812fc8SJiri Olsa 	 *
128789812fc8SJiri Olsa 	 *  0 - SAMPLE_IP can have arbitrary skid
128889812fc8SJiri Olsa 	 *  1 - SAMPLE_IP must have constant skid
128989812fc8SJiri Olsa 	 *  2 - SAMPLE_IP requested to have 0 skid
129089812fc8SJiri Olsa 	 *  3 - SAMPLE_IP must have 0 skid
129189812fc8SJiri Olsa 	 *
129289812fc8SJiri Olsa 	 *  See also PERF_RECORD_MISC_EXACT_IP
129386470930SIngo Molnar 	 */
129489812fc8SJiri Olsa 	if (precise > 3)
129589812fc8SJiri Olsa 		return -EINVAL;
129686470930SIngo Molnar 
1297f5b1135bSJiri Olsa 	mod->eu = eu;
1298f5b1135bSJiri Olsa 	mod->ek = ek;
1299f5b1135bSJiri Olsa 	mod->eh = eh;
1300f5b1135bSJiri Olsa 	mod->eH = eH;
1301f5b1135bSJiri Olsa 	mod->eG = eG;
1302a1e12da4SJiri Olsa 	mod->eI = eI;
1303f5b1135bSJiri Olsa 	mod->precise = precise;
13047f94af7aSJiri Olsa 	mod->precise_max = precise_max;
1305f5b1135bSJiri Olsa 	mod->exclude_GH = exclude_GH;
13063c176311SJiri Olsa 	mod->sample_read = sample_read;
1307e9a7c414SMichael Ellerman 	mod->pinned = pinned;
1308e9a7c414SMichael Ellerman 
1309f5b1135bSJiri Olsa 	return 0;
1310f5b1135bSJiri Olsa }
1311f5b1135bSJiri Olsa 
1312534123f4SJiri Olsa /*
1313534123f4SJiri Olsa  * Basic modifier sanity check to validate it contains only one
1314534123f4SJiri Olsa  * instance of any modifier (apart from 'p') present.
1315534123f4SJiri Olsa  */
1316534123f4SJiri Olsa static int check_modifier(char *str)
1317534123f4SJiri Olsa {
1318534123f4SJiri Olsa 	char *p = str;
1319534123f4SJiri Olsa 
1320534123f4SJiri Olsa 	/* The sizeof includes 0 byte as well. */
13217f94af7aSJiri Olsa 	if (strlen(str) > (sizeof("ukhGHpppPSDI") - 1))
1322534123f4SJiri Olsa 		return -1;
1323534123f4SJiri Olsa 
1324534123f4SJiri Olsa 	while (*p) {
1325534123f4SJiri Olsa 		if (*p != 'p' && strchr(p + 1, *p))
1326534123f4SJiri Olsa 			return -1;
1327534123f4SJiri Olsa 		p++;
1328534123f4SJiri Olsa 	}
1329534123f4SJiri Olsa 
1330534123f4SJiri Olsa 	return 0;
1331534123f4SJiri Olsa }
1332534123f4SJiri Olsa 
1333f5b1135bSJiri Olsa int parse_events__modifier_event(struct list_head *list, char *str, bool add)
1334f5b1135bSJiri Olsa {
1335f5b1135bSJiri Olsa 	struct perf_evsel *evsel;
1336f5b1135bSJiri Olsa 	struct event_modifier mod;
1337f5b1135bSJiri Olsa 
1338f5b1135bSJiri Olsa 	if (str == NULL)
1339f5b1135bSJiri Olsa 		return 0;
1340f5b1135bSJiri Olsa 
1341534123f4SJiri Olsa 	if (check_modifier(str))
1342534123f4SJiri Olsa 		return -EINVAL;
1343534123f4SJiri Olsa 
1344f5b1135bSJiri Olsa 	if (!add && get_event_modifier(&mod, str, NULL))
1345f5b1135bSJiri Olsa 		return -EINVAL;
1346f5b1135bSJiri Olsa 
13470050f7aaSArnaldo Carvalho de Melo 	__evlist__for_each(list, evsel) {
1348f5b1135bSJiri Olsa 		if (add && get_event_modifier(&mod, str, evsel))
1349f5b1135bSJiri Olsa 			return -EINVAL;
1350f5b1135bSJiri Olsa 
1351f5b1135bSJiri Olsa 		evsel->attr.exclude_user   = mod.eu;
1352f5b1135bSJiri Olsa 		evsel->attr.exclude_kernel = mod.ek;
1353f5b1135bSJiri Olsa 		evsel->attr.exclude_hv     = mod.eh;
1354f5b1135bSJiri Olsa 		evsel->attr.precise_ip     = mod.precise;
1355f5b1135bSJiri Olsa 		evsel->attr.exclude_host   = mod.eH;
1356f5b1135bSJiri Olsa 		evsel->attr.exclude_guest  = mod.eG;
1357a1e12da4SJiri Olsa 		evsel->attr.exclude_idle   = mod.eI;
1358f5b1135bSJiri Olsa 		evsel->exclude_GH          = mod.exclude_GH;
13593c176311SJiri Olsa 		evsel->sample_read         = mod.sample_read;
13607f94af7aSJiri Olsa 		evsel->precise_max         = mod.precise_max;
1361e9a7c414SMichael Ellerman 
1362e9a7c414SMichael Ellerman 		if (perf_evsel__is_group_leader(evsel))
1363e9a7c414SMichael Ellerman 			evsel->attr.pinned = mod.pinned;
1364ceb53fbfSIngo Molnar 	}
136586470930SIngo Molnar 
136689812fc8SJiri Olsa 	return 0;
136786470930SIngo Molnar }
136886470930SIngo Molnar 
1369ac2ba9f3SRobert Richter int parse_events_name(struct list_head *list, char *name)
1370ac2ba9f3SRobert Richter {
1371ac2ba9f3SRobert Richter 	struct perf_evsel *evsel;
1372ac2ba9f3SRobert Richter 
13730050f7aaSArnaldo Carvalho de Melo 	__evlist__for_each(list, evsel) {
1374ac2ba9f3SRobert Richter 		if (!evsel->name)
1375ac2ba9f3SRobert Richter 			evsel->name = strdup(name);
1376ac2ba9f3SRobert Richter 	}
1377ac2ba9f3SRobert Richter 
1378ac2ba9f3SRobert Richter 	return 0;
1379ac2ba9f3SRobert Richter }
1380ac2ba9f3SRobert Richter 
1381dcb4e102SKan Liang static int
1382dcb4e102SKan Liang comp_pmu(const void *p1, const void *p2)
1383dcb4e102SKan Liang {
1384dcb4e102SKan Liang 	struct perf_pmu_event_symbol *pmu1 = (struct perf_pmu_event_symbol *) p1;
1385dcb4e102SKan Liang 	struct perf_pmu_event_symbol *pmu2 = (struct perf_pmu_event_symbol *) p2;
1386dcb4e102SKan Liang 
1387dcb4e102SKan Liang 	return strcmp(pmu1->symbol, pmu2->symbol);
1388dcb4e102SKan Liang }
1389dcb4e102SKan Liang 
1390dcb4e102SKan Liang static void perf_pmu__parse_cleanup(void)
1391dcb4e102SKan Liang {
1392dcb4e102SKan Liang 	if (perf_pmu_events_list_num > 0) {
1393dcb4e102SKan Liang 		struct perf_pmu_event_symbol *p;
1394dcb4e102SKan Liang 		int i;
1395dcb4e102SKan Liang 
1396dcb4e102SKan Liang 		for (i = 0; i < perf_pmu_events_list_num; i++) {
1397dcb4e102SKan Liang 			p = perf_pmu_events_list + i;
1398dcb4e102SKan Liang 			free(p->symbol);
1399dcb4e102SKan Liang 		}
1400dcb4e102SKan Liang 		free(perf_pmu_events_list);
1401dcb4e102SKan Liang 		perf_pmu_events_list = NULL;
1402dcb4e102SKan Liang 		perf_pmu_events_list_num = 0;
1403dcb4e102SKan Liang 	}
1404dcb4e102SKan Liang }
1405dcb4e102SKan Liang 
1406dcb4e102SKan Liang #define SET_SYMBOL(str, stype)		\
1407dcb4e102SKan Liang do {					\
1408dcb4e102SKan Liang 	p->symbol = str;		\
1409dcb4e102SKan Liang 	if (!p->symbol)			\
1410dcb4e102SKan Liang 		goto err;		\
1411dcb4e102SKan Liang 	p->type = stype;		\
1412dcb4e102SKan Liang } while (0)
1413dcb4e102SKan Liang 
1414dcb4e102SKan Liang /*
1415dcb4e102SKan Liang  * Read the pmu events list from sysfs
1416dcb4e102SKan Liang  * Save it into perf_pmu_events_list
1417dcb4e102SKan Liang  */
1418dcb4e102SKan Liang static void perf_pmu__parse_init(void)
1419dcb4e102SKan Liang {
1420dcb4e102SKan Liang 
1421dcb4e102SKan Liang 	struct perf_pmu *pmu = NULL;
1422dcb4e102SKan Liang 	struct perf_pmu_alias *alias;
1423dcb4e102SKan Liang 	int len = 0;
1424dcb4e102SKan Liang 
1425dcb4e102SKan Liang 	pmu = perf_pmu__find("cpu");
1426dcb4e102SKan Liang 	if ((pmu == NULL) || list_empty(&pmu->aliases)) {
1427dcb4e102SKan Liang 		perf_pmu_events_list_num = -1;
1428dcb4e102SKan Liang 		return;
1429dcb4e102SKan Liang 	}
1430dcb4e102SKan Liang 	list_for_each_entry(alias, &pmu->aliases, list) {
1431dcb4e102SKan Liang 		if (strchr(alias->name, '-'))
1432dcb4e102SKan Liang 			len++;
1433dcb4e102SKan Liang 		len++;
1434dcb4e102SKan Liang 	}
1435dcb4e102SKan Liang 	perf_pmu_events_list = malloc(sizeof(struct perf_pmu_event_symbol) * len);
1436dcb4e102SKan Liang 	if (!perf_pmu_events_list)
1437dcb4e102SKan Liang 		return;
1438dcb4e102SKan Liang 	perf_pmu_events_list_num = len;
1439dcb4e102SKan Liang 
1440dcb4e102SKan Liang 	len = 0;
1441dcb4e102SKan Liang 	list_for_each_entry(alias, &pmu->aliases, list) {
1442dcb4e102SKan Liang 		struct perf_pmu_event_symbol *p = perf_pmu_events_list + len;
1443dcb4e102SKan Liang 		char *tmp = strchr(alias->name, '-');
1444dcb4e102SKan Liang 
1445dcb4e102SKan Liang 		if (tmp != NULL) {
1446dcb4e102SKan Liang 			SET_SYMBOL(strndup(alias->name, tmp - alias->name),
1447dcb4e102SKan Liang 					PMU_EVENT_SYMBOL_PREFIX);
1448dcb4e102SKan Liang 			p++;
1449dcb4e102SKan Liang 			SET_SYMBOL(strdup(++tmp), PMU_EVENT_SYMBOL_SUFFIX);
1450dcb4e102SKan Liang 			len += 2;
1451dcb4e102SKan Liang 		} else {
1452dcb4e102SKan Liang 			SET_SYMBOL(strdup(alias->name), PMU_EVENT_SYMBOL);
1453dcb4e102SKan Liang 			len++;
1454dcb4e102SKan Liang 		}
1455dcb4e102SKan Liang 	}
1456dcb4e102SKan Liang 	qsort(perf_pmu_events_list, len,
1457dcb4e102SKan Liang 		sizeof(struct perf_pmu_event_symbol), comp_pmu);
1458dcb4e102SKan Liang 
1459dcb4e102SKan Liang 	return;
1460dcb4e102SKan Liang err:
1461dcb4e102SKan Liang 	perf_pmu__parse_cleanup();
1462dcb4e102SKan Liang }
1463dcb4e102SKan Liang 
1464dcb4e102SKan Liang enum perf_pmu_event_symbol_type
1465dcb4e102SKan Liang perf_pmu__parse_check(const char *name)
1466dcb4e102SKan Liang {
1467dcb4e102SKan Liang 	struct perf_pmu_event_symbol p, *r;
1468dcb4e102SKan Liang 
1469dcb4e102SKan Liang 	/* scan kernel pmu events from sysfs if needed */
1470dcb4e102SKan Liang 	if (perf_pmu_events_list_num == 0)
1471dcb4e102SKan Liang 		perf_pmu__parse_init();
1472dcb4e102SKan Liang 	/*
1473dcb4e102SKan Liang 	 * name "cpu" could be prefix of cpu-cycles or cpu// events.
1474dcb4e102SKan Liang 	 * cpu-cycles has been handled by hardcode.
1475dcb4e102SKan Liang 	 * So it must be cpu// events, not kernel pmu event.
1476dcb4e102SKan Liang 	 */
1477dcb4e102SKan Liang 	if ((perf_pmu_events_list_num <= 0) || !strcmp(name, "cpu"))
1478dcb4e102SKan Liang 		return PMU_EVENT_SYMBOL_ERR;
1479dcb4e102SKan Liang 
1480dcb4e102SKan Liang 	p.symbol = strdup(name);
1481dcb4e102SKan Liang 	r = bsearch(&p, perf_pmu_events_list,
1482dcb4e102SKan Liang 			(size_t) perf_pmu_events_list_num,
1483dcb4e102SKan Liang 			sizeof(struct perf_pmu_event_symbol), comp_pmu);
1484dcb4e102SKan Liang 	free(p.symbol);
1485dcb4e102SKan Liang 	return r ? r->type : PMU_EVENT_SYMBOL_ERR;
1486dcb4e102SKan Liang }
1487dcb4e102SKan Liang 
148890e2b22dSJiri Olsa static int parse_events__scanner(const char *str, void *data, int start_token)
1489ac20de6fSZheng Yan {
1490ac20de6fSZheng Yan 	YY_BUFFER_STATE buffer;
1491ac20de6fSZheng Yan 	void *scanner;
1492ac20de6fSZheng Yan 	int ret;
1493ac20de6fSZheng Yan 
149490e2b22dSJiri Olsa 	ret = parse_events_lex_init_extra(start_token, &scanner);
1495ac20de6fSZheng Yan 	if (ret)
1496ac20de6fSZheng Yan 		return ret;
1497ac20de6fSZheng Yan 
1498ac20de6fSZheng Yan 	buffer = parse_events__scan_string(str, scanner);
1499ac20de6fSZheng Yan 
1500ac20de6fSZheng Yan #ifdef PARSER_DEBUG
1501ac20de6fSZheng Yan 	parse_events_debug = 1;
1502ac20de6fSZheng Yan #endif
1503ac20de6fSZheng Yan 	ret = parse_events_parse(data, scanner);
1504ac20de6fSZheng Yan 
1505ac20de6fSZheng Yan 	parse_events__flush_buffer(buffer, scanner);
1506ac20de6fSZheng Yan 	parse_events__delete_buffer(buffer, scanner);
1507ac20de6fSZheng Yan 	parse_events_lex_destroy(scanner);
1508ac20de6fSZheng Yan 	return ret;
1509ac20de6fSZheng Yan }
1510ac20de6fSZheng Yan 
151190e2b22dSJiri Olsa /*
151290e2b22dSJiri Olsa  * parse event config string, return a list of event terms.
151390e2b22dSJiri Olsa  */
151490e2b22dSJiri Olsa int parse_events_terms(struct list_head *terms, const char *str)
151590e2b22dSJiri Olsa {
151623b6339bSArnaldo Carvalho de Melo 	struct parse_events_terms data = {
151790e2b22dSJiri Olsa 		.terms = NULL,
151890e2b22dSJiri Olsa 	};
151990e2b22dSJiri Olsa 	int ret;
152090e2b22dSJiri Olsa 
152190e2b22dSJiri Olsa 	ret = parse_events__scanner(str, &data, PE_START_TERMS);
152290e2b22dSJiri Olsa 	if (!ret) {
152390e2b22dSJiri Olsa 		list_splice(data.terms, terms);
152474cf249dSArnaldo Carvalho de Melo 		zfree(&data.terms);
152590e2b22dSJiri Olsa 		return 0;
152690e2b22dSJiri Olsa 	}
152790e2b22dSJiri Olsa 
15282146afc6SArnaldo Carvalho de Melo 	parse_events_terms__delete(data.terms);
152990e2b22dSJiri Olsa 	return ret;
153090e2b22dSJiri Olsa }
153190e2b22dSJiri Olsa 
1532b39b8393SJiri Olsa int parse_events(struct perf_evlist *evlist, const char *str,
1533b39b8393SJiri Olsa 		 struct parse_events_error *err)
153486470930SIngo Molnar {
153523b6339bSArnaldo Carvalho de Melo 	struct parse_events_evlist data = {
153646010ab2SJiri Olsa 		.list   = LIST_HEAD_INIT(data.list),
153746010ab2SJiri Olsa 		.idx    = evlist->nr_entries,
1538b39b8393SJiri Olsa 		.error  = err,
15397630b3e2SWang Nan 		.evlist = evlist,
154046010ab2SJiri Olsa 	};
154146010ab2SJiri Olsa 	int ret;
154286470930SIngo Molnar 
154390e2b22dSJiri Olsa 	ret = parse_events__scanner(str, &data, PE_START_EVENTS);
1544dcb4e102SKan Liang 	perf_pmu__parse_cleanup();
154589812fc8SJiri Olsa 	if (!ret) {
154615bfd2ccSWang Nan 		struct perf_evsel *last;
154715bfd2ccSWang Nan 
1548854f7363SWang Nan 		if (list_empty(&data.list)) {
1549854f7363SWang Nan 			WARN_ONCE(true, "WARNING: event parser found nothing");
1550854f7363SWang Nan 			return -1;
1551854f7363SWang Nan 		}
1552854f7363SWang Nan 
1553f114d6efSAdrian Hunter 		perf_evlist__splice_list_tail(evlist, &data.list);
155497f63e4aSNamhyung Kim 		evlist->nr_groups += data.nr_groups;
155515bfd2ccSWang Nan 		last = perf_evlist__last(evlist);
155615bfd2ccSWang Nan 		last->cmdline_group_boundary = true;
155715bfd2ccSWang Nan 
155886470930SIngo Molnar 		return 0;
155986470930SIngo Molnar 	}
156086470930SIngo Molnar 
15615d7be90eSJiri Olsa 	/*
15625d7be90eSJiri Olsa 	 * There are 2 users - builtin-record and builtin-test objects.
15635d7be90eSJiri Olsa 	 * Both call perf_evlist__delete in case of error, so we dont
15645d7be90eSJiri Olsa 	 * need to bother.
15655d7be90eSJiri Olsa 	 */
156689812fc8SJiri Olsa 	return ret;
156789812fc8SJiri Olsa }
156889812fc8SJiri Olsa 
1569b39b8393SJiri Olsa #define MAX_WIDTH 1000
1570b39b8393SJiri Olsa static int get_term_width(void)
1571b39b8393SJiri Olsa {
1572b39b8393SJiri Olsa 	struct winsize ws;
1573b39b8393SJiri Olsa 
1574b39b8393SJiri Olsa 	get_term_dimensions(&ws);
1575b39b8393SJiri Olsa 	return ws.ws_col > MAX_WIDTH ? MAX_WIDTH : ws.ws_col;
1576b39b8393SJiri Olsa }
1577b39b8393SJiri Olsa 
1578b39b8393SJiri Olsa static void parse_events_print_error(struct parse_events_error *err,
1579b39b8393SJiri Olsa 				     const char *event)
1580b39b8393SJiri Olsa {
1581b39b8393SJiri Olsa 	const char *str = "invalid or unsupported event: ";
1582b39b8393SJiri Olsa 	char _buf[MAX_WIDTH];
1583b39b8393SJiri Olsa 	char *buf = (char *) event;
1584b39b8393SJiri Olsa 	int idx = 0;
1585b39b8393SJiri Olsa 
1586b39b8393SJiri Olsa 	if (err->str) {
1587b39b8393SJiri Olsa 		/* -2 for extra '' in the final fprintf */
1588b39b8393SJiri Olsa 		int width       = get_term_width() - 2;
1589b39b8393SJiri Olsa 		int len_event   = strlen(event);
1590b39b8393SJiri Olsa 		int len_str, max_len, cut = 0;
1591b39b8393SJiri Olsa 
1592b39b8393SJiri Olsa 		/*
1593b39b8393SJiri Olsa 		 * Maximum error index indent, we will cut
1594b39b8393SJiri Olsa 		 * the event string if it's bigger.
1595b39b8393SJiri Olsa 		 */
1596141b2d31SAdrian Hunter 		int max_err_idx = 13;
1597b39b8393SJiri Olsa 
1598b39b8393SJiri Olsa 		/*
1599b39b8393SJiri Olsa 		 * Let's be specific with the message when
1600b39b8393SJiri Olsa 		 * we have the precise error.
1601b39b8393SJiri Olsa 		 */
1602b39b8393SJiri Olsa 		str     = "event syntax error: ";
1603b39b8393SJiri Olsa 		len_str = strlen(str);
1604b39b8393SJiri Olsa 		max_len = width - len_str;
1605b39b8393SJiri Olsa 
1606b39b8393SJiri Olsa 		buf = _buf;
1607b39b8393SJiri Olsa 
1608b39b8393SJiri Olsa 		/* We're cutting from the beggining. */
1609b39b8393SJiri Olsa 		if (err->idx > max_err_idx)
1610b39b8393SJiri Olsa 			cut = err->idx - max_err_idx;
1611b39b8393SJiri Olsa 
1612b39b8393SJiri Olsa 		strncpy(buf, event + cut, max_len);
1613b39b8393SJiri Olsa 
1614b39b8393SJiri Olsa 		/* Mark cut parts with '..' on both sides. */
1615b39b8393SJiri Olsa 		if (cut)
1616b39b8393SJiri Olsa 			buf[0] = buf[1] = '.';
1617b39b8393SJiri Olsa 
1618b39b8393SJiri Olsa 		if ((len_event - cut) > max_len) {
1619b39b8393SJiri Olsa 			buf[max_len - 1] = buf[max_len - 2] = '.';
1620b39b8393SJiri Olsa 			buf[max_len] = 0;
1621b39b8393SJiri Olsa 		}
1622b39b8393SJiri Olsa 
1623b39b8393SJiri Olsa 		idx = len_str + err->idx - cut;
1624b39b8393SJiri Olsa 	}
1625b39b8393SJiri Olsa 
1626b39b8393SJiri Olsa 	fprintf(stderr, "%s'%s'\n", str, buf);
1627b39b8393SJiri Olsa 	if (idx) {
1628b39b8393SJiri Olsa 		fprintf(stderr, "%*s\\___ %s\n", idx + 1, "", err->str);
1629b39b8393SJiri Olsa 		if (err->help)
1630b39b8393SJiri Olsa 			fprintf(stderr, "\n%s\n", err->help);
1631b39b8393SJiri Olsa 		free(err->str);
1632b39b8393SJiri Olsa 		free(err->help);
1633b39b8393SJiri Olsa 	}
1634b39b8393SJiri Olsa 
1635b39b8393SJiri Olsa 	fprintf(stderr, "Run 'perf list' for a list of valid events\n");
1636b39b8393SJiri Olsa }
1637b39b8393SJiri Olsa 
1638b39b8393SJiri Olsa #undef MAX_WIDTH
1639b39b8393SJiri Olsa 
1640f120f9d5SJiri Olsa int parse_events_option(const struct option *opt, const char *str,
16411d037ca1SIrina Tirdea 			int unset __maybe_unused)
1642f120f9d5SJiri Olsa {
1643f120f9d5SJiri Olsa 	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
1644b39b8393SJiri Olsa 	struct parse_events_error err = { .idx = 0, };
1645b39b8393SJiri Olsa 	int ret = parse_events(evlist, str, &err);
16469175ce1fSAndi Kleen 
1647b39b8393SJiri Olsa 	if (ret)
1648b39b8393SJiri Olsa 		parse_events_print_error(&err, str);
1649b39b8393SJiri Olsa 
16509175ce1fSAndi Kleen 	return ret;
1651f120f9d5SJiri Olsa }
1652f120f9d5SJiri Olsa 
16534ba1faa1SWang Nan static int
16544ba1faa1SWang Nan foreach_evsel_in_last_glob(struct perf_evlist *evlist,
16554ba1faa1SWang Nan 			   int (*func)(struct perf_evsel *evsel,
16564ba1faa1SWang Nan 				       const void *arg),
16574ba1faa1SWang Nan 			   const void *arg)
1658c171b552SLi Zefan {
165969aad6f1SArnaldo Carvalho de Melo 	struct perf_evsel *last = NULL;
16604ba1faa1SWang Nan 	int err;
1661c171b552SLi Zefan 
1662854f7363SWang Nan 	/*
1663854f7363SWang Nan 	 * Don't return when list_empty, give func a chance to report
1664854f7363SWang Nan 	 * error when it found last == NULL.
1665854f7363SWang Nan 	 *
1666854f7363SWang Nan 	 * So no need to WARN here, let *func do this.
1667854f7363SWang Nan 	 */
1668361c99a6SArnaldo Carvalho de Melo 	if (evlist->nr_entries > 0)
16690c21f736SArnaldo Carvalho de Melo 		last = perf_evlist__last(evlist);
167069aad6f1SArnaldo Carvalho de Melo 
167115bfd2ccSWang Nan 	do {
16724ba1faa1SWang Nan 		err = (*func)(last, arg);
16734ba1faa1SWang Nan 		if (err)
1674c171b552SLi Zefan 			return -1;
16754ba1faa1SWang Nan 		if (!last)
16764ba1faa1SWang Nan 			return 0;
1677c171b552SLi Zefan 
167815bfd2ccSWang Nan 		if (last->node.prev == &evlist->entries)
167915bfd2ccSWang Nan 			return 0;
168015bfd2ccSWang Nan 		last = list_entry(last->node.prev, struct perf_evsel, node);
168115bfd2ccSWang Nan 	} while (!last->cmdline_group_boundary);
168215bfd2ccSWang Nan 
1683c171b552SLi Zefan 	return 0;
1684c171b552SLi Zefan }
1685c171b552SLi Zefan 
16864ba1faa1SWang Nan static int set_filter(struct perf_evsel *evsel, const void *arg)
16874ba1faa1SWang Nan {
16884ba1faa1SWang Nan 	const char *str = arg;
16894ba1faa1SWang Nan 
16904ba1faa1SWang Nan 	if (evsel == NULL || evsel->attr.type != PERF_TYPE_TRACEPOINT) {
16914ba1faa1SWang Nan 		fprintf(stderr,
16924ba1faa1SWang Nan 			"--filter option should follow a -e tracepoint option\n");
16934ba1faa1SWang Nan 		return -1;
16944ba1faa1SWang Nan 	}
16954ba1faa1SWang Nan 
16964ba1faa1SWang Nan 	if (perf_evsel__append_filter(evsel, "&&", str) < 0) {
16974ba1faa1SWang Nan 		fprintf(stderr,
16984ba1faa1SWang Nan 			"not enough memory to hold filter string\n");
16994ba1faa1SWang Nan 		return -1;
17004ba1faa1SWang Nan 	}
17014ba1faa1SWang Nan 
17024ba1faa1SWang Nan 	return 0;
17034ba1faa1SWang Nan }
17044ba1faa1SWang Nan 
17054ba1faa1SWang Nan int parse_filter(const struct option *opt, const char *str,
17064ba1faa1SWang Nan 		 int unset __maybe_unused)
17074ba1faa1SWang Nan {
17084ba1faa1SWang Nan 	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
17094ba1faa1SWang Nan 
17104ba1faa1SWang Nan 	return foreach_evsel_in_last_glob(evlist, set_filter,
17114ba1faa1SWang Nan 					  (const void *)str);
17124ba1faa1SWang Nan }
17134ba1faa1SWang Nan 
17144ba1faa1SWang Nan static int add_exclude_perf_filter(struct perf_evsel *evsel,
17154ba1faa1SWang Nan 				   const void *arg __maybe_unused)
17164ba1faa1SWang Nan {
17174ba1faa1SWang Nan 	char new_filter[64];
17184ba1faa1SWang Nan 
17194ba1faa1SWang Nan 	if (evsel == NULL || evsel->attr.type != PERF_TYPE_TRACEPOINT) {
17204ba1faa1SWang Nan 		fprintf(stderr,
17214ba1faa1SWang Nan 			"--exclude-perf option should follow a -e tracepoint option\n");
17224ba1faa1SWang Nan 		return -1;
17234ba1faa1SWang Nan 	}
17244ba1faa1SWang Nan 
17254ba1faa1SWang Nan 	snprintf(new_filter, sizeof(new_filter), "common_pid != %d", getpid());
17264ba1faa1SWang Nan 
17274ba1faa1SWang Nan 	if (perf_evsel__append_filter(evsel, "&&", new_filter) < 0) {
17284ba1faa1SWang Nan 		fprintf(stderr,
17294ba1faa1SWang Nan 			"not enough memory to hold filter string\n");
17304ba1faa1SWang Nan 		return -1;
17314ba1faa1SWang Nan 	}
17324ba1faa1SWang Nan 
17334ba1faa1SWang Nan 	return 0;
17344ba1faa1SWang Nan }
17354ba1faa1SWang Nan 
17364ba1faa1SWang Nan int exclude_perf(const struct option *opt,
17374ba1faa1SWang Nan 		 const char *arg __maybe_unused,
17384ba1faa1SWang Nan 		 int unset __maybe_unused)
17394ba1faa1SWang Nan {
17404ba1faa1SWang Nan 	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
17414ba1faa1SWang Nan 
17424ba1faa1SWang Nan 	return foreach_evsel_in_last_glob(evlist, add_exclude_perf_filter,
17434ba1faa1SWang Nan 					  NULL);
17444ba1faa1SWang Nan }
17454ba1faa1SWang Nan 
174686470930SIngo Molnar static const char * const event_type_descriptors[] = {
174786470930SIngo Molnar 	"Hardware event",
174886470930SIngo Molnar 	"Software event",
174986470930SIngo Molnar 	"Tracepoint event",
175086470930SIngo Molnar 	"Hardware cache event",
175141bdcb23SLiming Wang 	"Raw hardware event descriptor",
175241bdcb23SLiming Wang 	"Hardware breakpoint",
175386470930SIngo Molnar };
175486470930SIngo Molnar 
1755ab0e4800SYunlong Song static int cmp_string(const void *a, const void *b)
1756ab0e4800SYunlong Song {
1757ab0e4800SYunlong Song 	const char * const *as = a;
1758ab0e4800SYunlong Song 	const char * const *bs = b;
1759ab0e4800SYunlong Song 
1760ab0e4800SYunlong Song 	return strcmp(*as, *bs);
1761ab0e4800SYunlong Song }
1762ab0e4800SYunlong Song 
176386470930SIngo Molnar /*
1764f6bdafefSJason Baron  * Print the events from <debugfs_mount_point>/tracing/events
1765f6bdafefSJason Baron  */
1766f6bdafefSJason Baron 
1767a3277d2dSFrederic Weisbecker void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
1768a3277d2dSFrederic Weisbecker 			     bool name_only)
1769f6bdafefSJason Baron {
1770f6bdafefSJason Baron 	DIR *sys_dir, *evt_dir;
1771f6bdafefSJason Baron 	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
1772f6bdafefSJason Baron 	char evt_path[MAXPATHLEN];
1773725b1368SEric Dumazet 	char dir_path[MAXPATHLEN];
1774ab0e4800SYunlong Song 	char **evt_list = NULL;
1775ab0e4800SYunlong Song 	unsigned int evt_i = 0, evt_num = 0;
1776ab0e4800SYunlong Song 	bool evt_num_known = false;
1777f6bdafefSJason Baron 
1778ab0e4800SYunlong Song restart:
1779ebf294bfSArnaldo Carvalho de Melo 	sys_dir = opendir(tracing_events_path);
1780f6bdafefSJason Baron 	if (!sys_dir)
1781725b1368SEric Dumazet 		return;
1782f6bdafefSJason Baron 
1783ab0e4800SYunlong Song 	if (evt_num_known) {
1784ab0e4800SYunlong Song 		evt_list = zalloc(sizeof(char *) * evt_num);
1785ab0e4800SYunlong Song 		if (!evt_list)
1786ab0e4800SYunlong Song 			goto out_close_sys_dir;
1787ab0e4800SYunlong Song 	}
1788ab0e4800SYunlong Song 
17896b58e7f1SUlrich Drepper 	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
1790668b8788SArnaldo Carvalho de Melo 		if (subsys_glob != NULL &&
1791668b8788SArnaldo Carvalho de Melo 		    !strglobmatch(sys_dirent.d_name, subsys_glob))
1792668b8788SArnaldo Carvalho de Melo 			continue;
1793725b1368SEric Dumazet 
1794ebf294bfSArnaldo Carvalho de Melo 		snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
1795725b1368SEric Dumazet 			 sys_dirent.d_name);
1796725b1368SEric Dumazet 		evt_dir = opendir(dir_path);
1797725b1368SEric Dumazet 		if (!evt_dir)
17986b58e7f1SUlrich Drepper 			continue;
1799725b1368SEric Dumazet 
18006b58e7f1SUlrich Drepper 		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
1801668b8788SArnaldo Carvalho de Melo 			if (event_glob != NULL &&
1802668b8788SArnaldo Carvalho de Melo 			    !strglobmatch(evt_dirent.d_name, event_glob))
1803668b8788SArnaldo Carvalho de Melo 				continue;
1804668b8788SArnaldo Carvalho de Melo 
1805ab0e4800SYunlong Song 			if (!evt_num_known) {
1806ab0e4800SYunlong Song 				evt_num++;
1807a3277d2dSFrederic Weisbecker 				continue;
1808a3277d2dSFrederic Weisbecker 			}
1809a3277d2dSFrederic Weisbecker 
1810f6bdafefSJason Baron 			snprintf(evt_path, MAXPATHLEN, "%s:%s",
1811f6bdafefSJason Baron 				 sys_dirent.d_name, evt_dirent.d_name);
1812ab0e4800SYunlong Song 
1813ab0e4800SYunlong Song 			evt_list[evt_i] = strdup(evt_path);
1814ab0e4800SYunlong Song 			if (evt_list[evt_i] == NULL)
1815ab0e4800SYunlong Song 				goto out_close_evt_dir;
1816ab0e4800SYunlong Song 			evt_i++;
1817f6bdafefSJason Baron 		}
1818f6bdafefSJason Baron 		closedir(evt_dir);
1819f6bdafefSJason Baron 	}
1820f6bdafefSJason Baron 	closedir(sys_dir);
1821ab0e4800SYunlong Song 
1822ab0e4800SYunlong Song 	if (!evt_num_known) {
1823ab0e4800SYunlong Song 		evt_num_known = true;
1824ab0e4800SYunlong Song 		goto restart;
1825ab0e4800SYunlong Song 	}
1826ab0e4800SYunlong Song 	qsort(evt_list, evt_num, sizeof(char *), cmp_string);
1827ab0e4800SYunlong Song 	evt_i = 0;
1828ab0e4800SYunlong Song 	while (evt_i < evt_num) {
1829ab0e4800SYunlong Song 		if (name_only) {
1830ab0e4800SYunlong Song 			printf("%s ", evt_list[evt_i++]);
1831ab0e4800SYunlong Song 			continue;
1832ab0e4800SYunlong Song 		}
1833ab0e4800SYunlong Song 		printf("  %-50s [%s]\n", evt_list[evt_i++],
1834ab0e4800SYunlong Song 				event_type_descriptors[PERF_TYPE_TRACEPOINT]);
1835ab0e4800SYunlong Song 	}
1836dfc431cbSArnaldo Carvalho de Melo 	if (evt_num && pager_in_use())
1837ab0e4800SYunlong Song 		printf("\n");
1838ab0e4800SYunlong Song 
1839ab0e4800SYunlong Song out_free:
1840ab0e4800SYunlong Song 	evt_num = evt_i;
1841ab0e4800SYunlong Song 	for (evt_i = 0; evt_i < evt_num; evt_i++)
1842ab0e4800SYunlong Song 		zfree(&evt_list[evt_i]);
1843ab0e4800SYunlong Song 	zfree(&evt_list);
1844ab0e4800SYunlong Song 	return;
1845ab0e4800SYunlong Song 
1846ab0e4800SYunlong Song out_close_evt_dir:
1847ab0e4800SYunlong Song 	closedir(evt_dir);
1848ab0e4800SYunlong Song out_close_sys_dir:
1849ab0e4800SYunlong Song 	closedir(sys_dir);
1850ab0e4800SYunlong Song 
1851ab0e4800SYunlong Song 	printf("FATAL: not enough memory to print %s\n",
1852ab0e4800SYunlong Song 			event_type_descriptors[PERF_TYPE_TRACEPOINT]);
1853ab0e4800SYunlong Song 	if (evt_list)
1854ab0e4800SYunlong Song 		goto out_free;
1855f6bdafefSJason Baron }
1856f6bdafefSJason Baron 
1857f6bdafefSJason Baron /*
185820c457b8SThomas Renninger  * Check whether event is in <debugfs_mount_point>/tracing/events
185920c457b8SThomas Renninger  */
186020c457b8SThomas Renninger 
186120c457b8SThomas Renninger int is_valid_tracepoint(const char *event_string)
186220c457b8SThomas Renninger {
186320c457b8SThomas Renninger 	DIR *sys_dir, *evt_dir;
186420c457b8SThomas Renninger 	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
186520c457b8SThomas Renninger 	char evt_path[MAXPATHLEN];
186620c457b8SThomas Renninger 	char dir_path[MAXPATHLEN];
186720c457b8SThomas Renninger 
1868ebf294bfSArnaldo Carvalho de Melo 	sys_dir = opendir(tracing_events_path);
186920c457b8SThomas Renninger 	if (!sys_dir)
187020c457b8SThomas Renninger 		return 0;
187120c457b8SThomas Renninger 
187220c457b8SThomas Renninger 	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
187320c457b8SThomas Renninger 
1874ebf294bfSArnaldo Carvalho de Melo 		snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
187520c457b8SThomas Renninger 			 sys_dirent.d_name);
187620c457b8SThomas Renninger 		evt_dir = opendir(dir_path);
187720c457b8SThomas Renninger 		if (!evt_dir)
187820c457b8SThomas Renninger 			continue;
187920c457b8SThomas Renninger 
188020c457b8SThomas Renninger 		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
188120c457b8SThomas Renninger 			snprintf(evt_path, MAXPATHLEN, "%s:%s",
188220c457b8SThomas Renninger 				 sys_dirent.d_name, evt_dirent.d_name);
188320c457b8SThomas Renninger 			if (!strcmp(evt_path, event_string)) {
188420c457b8SThomas Renninger 				closedir(evt_dir);
188520c457b8SThomas Renninger 				closedir(sys_dir);
188620c457b8SThomas Renninger 				return 1;
188720c457b8SThomas Renninger 			}
188820c457b8SThomas Renninger 		}
188920c457b8SThomas Renninger 		closedir(evt_dir);
189020c457b8SThomas Renninger 	}
189120c457b8SThomas Renninger 	closedir(sys_dir);
189220c457b8SThomas Renninger 	return 0;
189320c457b8SThomas Renninger }
189420c457b8SThomas Renninger 
1895b41f1cecSNamhyung Kim static bool is_event_supported(u8 type, unsigned config)
1896b41f1cecSNamhyung Kim {
1897b41f1cecSNamhyung Kim 	bool ret = true;
189888fee52eSVince Weaver 	int open_return;
1899b41f1cecSNamhyung Kim 	struct perf_evsel *evsel;
1900b41f1cecSNamhyung Kim 	struct perf_event_attr attr = {
1901b41f1cecSNamhyung Kim 		.type = type,
1902b41f1cecSNamhyung Kim 		.config = config,
1903b41f1cecSNamhyung Kim 		.disabled = 1,
1904b41f1cecSNamhyung Kim 	};
1905b41f1cecSNamhyung Kim 	struct {
1906b41f1cecSNamhyung Kim 		struct thread_map map;
1907b41f1cecSNamhyung Kim 		int threads[1];
1908b41f1cecSNamhyung Kim 	} tmap = {
1909b41f1cecSNamhyung Kim 		.map.nr	 = 1,
1910b41f1cecSNamhyung Kim 		.threads = { 0 },
1911b41f1cecSNamhyung Kim 	};
1912b41f1cecSNamhyung Kim 
1913ef503831SArnaldo Carvalho de Melo 	evsel = perf_evsel__new(&attr);
1914b41f1cecSNamhyung Kim 	if (evsel) {
191588fee52eSVince Weaver 		open_return = perf_evsel__open(evsel, NULL, &tmap.map);
191688fee52eSVince Weaver 		ret = open_return >= 0;
191788fee52eSVince Weaver 
191888fee52eSVince Weaver 		if (open_return == -EACCES) {
191988fee52eSVince Weaver 			/*
192088fee52eSVince Weaver 			 * This happens if the paranoid value
192188fee52eSVince Weaver 			 * /proc/sys/kernel/perf_event_paranoid is set to 2
192288fee52eSVince Weaver 			 * Re-run with exclude_kernel set; we don't do that
192388fee52eSVince Weaver 			 * by default as some ARM machines do not support it.
192488fee52eSVince Weaver 			 *
192588fee52eSVince Weaver 			 */
192688fee52eSVince Weaver 			evsel->attr.exclude_kernel = 1;
1927b41f1cecSNamhyung Kim 			ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0;
192888fee52eSVince Weaver 		}
1929b41f1cecSNamhyung Kim 		perf_evsel__delete(evsel);
1930b41f1cecSNamhyung Kim 	}
1931b41f1cecSNamhyung Kim 
1932b41f1cecSNamhyung Kim 	return ret;
1933b41f1cecSNamhyung Kim }
1934b41f1cecSNamhyung Kim 
1935a3277d2dSFrederic Weisbecker int print_hwcache_events(const char *event_glob, bool name_only)
1936668b8788SArnaldo Carvalho de Melo {
1937ab0e4800SYunlong Song 	unsigned int type, op, i, evt_i = 0, evt_num = 0;
19380b668bc9SArnaldo Carvalho de Melo 	char name[64];
1939ab0e4800SYunlong Song 	char **evt_list = NULL;
1940ab0e4800SYunlong Song 	bool evt_num_known = false;
1941ab0e4800SYunlong Song 
1942ab0e4800SYunlong Song restart:
1943ab0e4800SYunlong Song 	if (evt_num_known) {
1944ab0e4800SYunlong Song 		evt_list = zalloc(sizeof(char *) * evt_num);
1945ab0e4800SYunlong Song 		if (!evt_list)
1946ab0e4800SYunlong Song 			goto out_enomem;
1947ab0e4800SYunlong Song 	}
1948668b8788SArnaldo Carvalho de Melo 
1949668b8788SArnaldo Carvalho de Melo 	for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
1950668b8788SArnaldo Carvalho de Melo 		for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
1951668b8788SArnaldo Carvalho de Melo 			/* skip invalid cache type */
19520b668bc9SArnaldo Carvalho de Melo 			if (!perf_evsel__is_cache_op_valid(type, op))
1953668b8788SArnaldo Carvalho de Melo 				continue;
1954668b8788SArnaldo Carvalho de Melo 
1955668b8788SArnaldo Carvalho de Melo 			for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
19560b668bc9SArnaldo Carvalho de Melo 				__perf_evsel__hw_cache_type_op_res_name(type, op, i,
19570b668bc9SArnaldo Carvalho de Melo 									name, sizeof(name));
1958947b4ad1SIngo Molnar 				if (event_glob != NULL && !strglobmatch(name, event_glob))
1959668b8788SArnaldo Carvalho de Melo 					continue;
1960668b8788SArnaldo Carvalho de Melo 
1961b41f1cecSNamhyung Kim 				if (!is_event_supported(PERF_TYPE_HW_CACHE,
1962b41f1cecSNamhyung Kim 							type | (op << 8) | (i << 16)))
1963b41f1cecSNamhyung Kim 					continue;
1964b41f1cecSNamhyung Kim 
1965ab0e4800SYunlong Song 				if (!evt_num_known) {
1966ab0e4800SYunlong Song 					evt_num++;
1967ab0e4800SYunlong Song 					continue;
1968ab0e4800SYunlong Song 				}
1969ab0e4800SYunlong Song 
1970ab0e4800SYunlong Song 				evt_list[evt_i] = strdup(name);
1971ab0e4800SYunlong Song 				if (evt_list[evt_i] == NULL)
1972ab0e4800SYunlong Song 					goto out_enomem;
1973ab0e4800SYunlong Song 				evt_i++;
1974668b8788SArnaldo Carvalho de Melo 			}
1975668b8788SArnaldo Carvalho de Melo 		}
1976668b8788SArnaldo Carvalho de Melo 	}
1977668b8788SArnaldo Carvalho de Melo 
1978ab0e4800SYunlong Song 	if (!evt_num_known) {
1979ab0e4800SYunlong Song 		evt_num_known = true;
1980ab0e4800SYunlong Song 		goto restart;
1981ab0e4800SYunlong Song 	}
1982ab0e4800SYunlong Song 	qsort(evt_list, evt_num, sizeof(char *), cmp_string);
1983ab0e4800SYunlong Song 	evt_i = 0;
1984ab0e4800SYunlong Song 	while (evt_i < evt_num) {
1985ab0e4800SYunlong Song 		if (name_only) {
1986ab0e4800SYunlong Song 			printf("%s ", evt_list[evt_i++]);
1987ab0e4800SYunlong Song 			continue;
1988ab0e4800SYunlong Song 		}
1989ab0e4800SYunlong Song 		printf("  %-50s [%s]\n", evt_list[evt_i++],
1990ab0e4800SYunlong Song 				event_type_descriptors[PERF_TYPE_HW_CACHE]);
1991ab0e4800SYunlong Song 	}
1992dfc431cbSArnaldo Carvalho de Melo 	if (evt_num && pager_in_use())
1993dc098b35SAndi Kleen 		printf("\n");
1994ab0e4800SYunlong Song 
1995ab0e4800SYunlong Song out_free:
1996ab0e4800SYunlong Song 	evt_num = evt_i;
1997ab0e4800SYunlong Song 	for (evt_i = 0; evt_i < evt_num; evt_i++)
1998ab0e4800SYunlong Song 		zfree(&evt_list[evt_i]);
1999ab0e4800SYunlong Song 	zfree(&evt_list);
2000ab0e4800SYunlong Song 	return evt_num;
2001ab0e4800SYunlong Song 
2002ab0e4800SYunlong Song out_enomem:
2003ab0e4800SYunlong Song 	printf("FATAL: not enough memory to print %s\n", event_type_descriptors[PERF_TYPE_HW_CACHE]);
2004ab0e4800SYunlong Song 	if (evt_list)
2005ab0e4800SYunlong Song 		goto out_free;
2006ab0e4800SYunlong Song 	return evt_num;
2007668b8788SArnaldo Carvalho de Melo }
2008668b8788SArnaldo Carvalho de Melo 
2009705750f2SYunlong Song void print_symbol_events(const char *event_glob, unsigned type,
2010a3277d2dSFrederic Weisbecker 				struct event_symbol *syms, unsigned max,
2011a3277d2dSFrederic Weisbecker 				bool name_only)
201286470930SIngo Molnar {
2013ab0e4800SYunlong Song 	unsigned int i, evt_i = 0, evt_num = 0;
2014947b4ad1SIngo Molnar 	char name[MAX_NAME_LEN];
2015ab0e4800SYunlong Song 	char **evt_list = NULL;
2016ab0e4800SYunlong Song 	bool evt_num_known = false;
2017ab0e4800SYunlong Song 
2018ab0e4800SYunlong Song restart:
2019ab0e4800SYunlong Song 	if (evt_num_known) {
2020ab0e4800SYunlong Song 		evt_list = zalloc(sizeof(char *) * evt_num);
2021ab0e4800SYunlong Song 		if (!evt_list)
2022ab0e4800SYunlong Song 			goto out_enomem;
2023ab0e4800SYunlong Song 		syms -= max;
2024ab0e4800SYunlong Song 	}
202586470930SIngo Molnar 
20261dc12760SJiri Olsa 	for (i = 0; i < max; i++, syms++) {
2027668b8788SArnaldo Carvalho de Melo 
2028e37df6c7SArnaldo Carvalho de Melo 		if (event_glob != NULL && syms->symbol != NULL &&
2029668b8788SArnaldo Carvalho de Melo 		    !(strglobmatch(syms->symbol, event_glob) ||
2030668b8788SArnaldo Carvalho de Melo 		      (syms->alias && strglobmatch(syms->alias, event_glob))))
2031668b8788SArnaldo Carvalho de Melo 			continue;
203286470930SIngo Molnar 
2033b41f1cecSNamhyung Kim 		if (!is_event_supported(type, i))
2034b41f1cecSNamhyung Kim 			continue;
2035b41f1cecSNamhyung Kim 
2036ab0e4800SYunlong Song 		if (!evt_num_known) {
2037ab0e4800SYunlong Song 			evt_num++;
2038a3277d2dSFrederic Weisbecker 			continue;
2039a3277d2dSFrederic Weisbecker 		}
2040a3277d2dSFrederic Weisbecker 
2041ab0e4800SYunlong Song 		if (!name_only && strlen(syms->alias))
2042947b4ad1SIngo Molnar 			snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
204374d5b588SJaswinder Singh Rajput 		else
2044947b4ad1SIngo Molnar 			strncpy(name, syms->symbol, MAX_NAME_LEN);
204586470930SIngo Molnar 
2046ab0e4800SYunlong Song 		evt_list[evt_i] = strdup(name);
2047ab0e4800SYunlong Song 		if (evt_list[evt_i] == NULL)
2048ab0e4800SYunlong Song 			goto out_enomem;
2049ab0e4800SYunlong Song 		evt_i++;
205086470930SIngo Molnar 	}
205186470930SIngo Molnar 
2052ab0e4800SYunlong Song 	if (!evt_num_known) {
2053ab0e4800SYunlong Song 		evt_num_known = true;
2054ab0e4800SYunlong Song 		goto restart;
2055ab0e4800SYunlong Song 	}
2056ab0e4800SYunlong Song 	qsort(evt_list, evt_num, sizeof(char *), cmp_string);
2057ab0e4800SYunlong Song 	evt_i = 0;
2058ab0e4800SYunlong Song 	while (evt_i < evt_num) {
2059ab0e4800SYunlong Song 		if (name_only) {
2060ab0e4800SYunlong Song 			printf("%s ", evt_list[evt_i++]);
2061ab0e4800SYunlong Song 			continue;
2062ab0e4800SYunlong Song 		}
2063ab0e4800SYunlong Song 		printf("  %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]);
2064ab0e4800SYunlong Song 	}
2065dfc431cbSArnaldo Carvalho de Melo 	if (evt_num && pager_in_use())
2066689d3018SMarti Raudsepp 		printf("\n");
2067ab0e4800SYunlong Song 
2068ab0e4800SYunlong Song out_free:
2069ab0e4800SYunlong Song 	evt_num = evt_i;
2070ab0e4800SYunlong Song 	for (evt_i = 0; evt_i < evt_num; evt_i++)
2071ab0e4800SYunlong Song 		zfree(&evt_list[evt_i]);
2072ab0e4800SYunlong Song 	zfree(&evt_list);
2073ab0e4800SYunlong Song 	return;
2074ab0e4800SYunlong Song 
2075ab0e4800SYunlong Song out_enomem:
2076ab0e4800SYunlong Song 	printf("FATAL: not enough memory to print %s\n", event_type_descriptors[type]);
2077ab0e4800SYunlong Song 	if (evt_list)
2078ab0e4800SYunlong Song 		goto out_free;
2079668b8788SArnaldo Carvalho de Melo }
20801dc12760SJiri Olsa 
20811dc12760SJiri Olsa /*
20821dc12760SJiri Olsa  * Print the help text for the event symbols:
20831dc12760SJiri Olsa  */
2084a3277d2dSFrederic Weisbecker void print_events(const char *event_glob, bool name_only)
20851dc12760SJiri Olsa {
20861dc12760SJiri Olsa 	print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
2087a3277d2dSFrederic Weisbecker 			    event_symbols_hw, PERF_COUNT_HW_MAX, name_only);
20881dc12760SJiri Olsa 
20891dc12760SJiri Olsa 	print_symbol_events(event_glob, PERF_TYPE_SOFTWARE,
2090a3277d2dSFrederic Weisbecker 			    event_symbols_sw, PERF_COUNT_SW_MAX, name_only);
20911dc12760SJiri Olsa 
2092a3277d2dSFrederic Weisbecker 	print_hwcache_events(event_glob, name_only);
209373c24cb8SJaswinder Singh Rajput 
2094dc098b35SAndi Kleen 	print_pmu_events(event_glob, name_only);
2095dc098b35SAndi Kleen 
2096668b8788SArnaldo Carvalho de Melo 	if (event_glob != NULL)
2097668b8788SArnaldo Carvalho de Melo 		return;
209873c24cb8SJaswinder Singh Rajput 
2099a3277d2dSFrederic Weisbecker 	if (!name_only) {
2100947b4ad1SIngo Molnar 		printf("  %-50s [%s]\n",
21015f537a26SJiri Olsa 		       "rNNN",
21021cf4a063SArnaldo Carvalho de Melo 		       event_type_descriptors[PERF_TYPE_RAW]);
21035f537a26SJiri Olsa 		printf("  %-50s [%s]\n",
21045f537a26SJiri Olsa 		       "cpu/t1=v1[,t2=v2,t3 ...]/modifier",
21055f537a26SJiri Olsa 		       event_type_descriptors[PERF_TYPE_RAW]);
2106dfc431cbSArnaldo Carvalho de Melo 		if (pager_in_use())
2107dfc431cbSArnaldo Carvalho de Melo 			printf("   (see 'man perf-list' on how to encode it)\n\n");
210886470930SIngo Molnar 
2109947b4ad1SIngo Molnar 		printf("  %-50s [%s]\n",
21103741eb9fSJacob Shin 		       "mem:<addr>[/len][:access]",
211141bdcb23SLiming Wang 			event_type_descriptors[PERF_TYPE_BREAKPOINT]);
2112dfc431cbSArnaldo Carvalho de Melo 		if (pager_in_use())
21131b290d67SFrederic Weisbecker 			printf("\n");
2114a3277d2dSFrederic Weisbecker 	}
21151b290d67SFrederic Weisbecker 
2116a3277d2dSFrederic Weisbecker 	print_tracepoint_events(NULL, NULL, name_only);
211786470930SIngo Molnar }
21188f707d84SJiri Olsa 
21196cee6cd3SArnaldo Carvalho de Melo int parse_events__is_hardcoded_term(struct parse_events_term *term)
21208f707d84SJiri Olsa {
212116fa7e82SJiri Olsa 	return term->type_term != PARSE_EVENTS__TERM_TYPE_USER;
21228f707d84SJiri Olsa }
21238f707d84SJiri Olsa 
21246cee6cd3SArnaldo Carvalho de Melo static int new_term(struct parse_events_term **_term, int type_val,
212516fa7e82SJiri Olsa 		    int type_term, char *config,
2126cecf3a2eSJiri Olsa 		    char *str, u64 num, int err_term, int err_val)
21278f707d84SJiri Olsa {
21286cee6cd3SArnaldo Carvalho de Melo 	struct parse_events_term *term;
21298f707d84SJiri Olsa 
21308f707d84SJiri Olsa 	term = zalloc(sizeof(*term));
21318f707d84SJiri Olsa 	if (!term)
21328f707d84SJiri Olsa 		return -ENOMEM;
21338f707d84SJiri Olsa 
21348f707d84SJiri Olsa 	INIT_LIST_HEAD(&term->list);
213516fa7e82SJiri Olsa 	term->type_val  = type_val;
213616fa7e82SJiri Olsa 	term->type_term = type_term;
21378f707d84SJiri Olsa 	term->config = config;
2138cecf3a2eSJiri Olsa 	term->err_term = err_term;
2139cecf3a2eSJiri Olsa 	term->err_val  = err_val;
21408f707d84SJiri Olsa 
214116fa7e82SJiri Olsa 	switch (type_val) {
21428f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_NUM:
21438f707d84SJiri Olsa 		term->val.num = num;
21448f707d84SJiri Olsa 		break;
21458f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_STR:
21468f707d84SJiri Olsa 		term->val.str = str;
21478f707d84SJiri Olsa 		break;
21488f707d84SJiri Olsa 	default:
21494be8be6bSAdrian Hunter 		free(term);
21508f707d84SJiri Olsa 		return -EINVAL;
21518f707d84SJiri Olsa 	}
21528f707d84SJiri Olsa 
21538f707d84SJiri Olsa 	*_term = term;
21548f707d84SJiri Olsa 	return 0;
21558f707d84SJiri Olsa }
21568f707d84SJiri Olsa 
21576cee6cd3SArnaldo Carvalho de Melo int parse_events_term__num(struct parse_events_term **term,
2158cecf3a2eSJiri Olsa 			   int type_term, char *config, u64 num,
2159bb78ce7dSAdrian Hunter 			   void *loc_term_, void *loc_val_)
216016fa7e82SJiri Olsa {
2161bb78ce7dSAdrian Hunter 	YYLTYPE *loc_term = loc_term_;
2162bb78ce7dSAdrian Hunter 	YYLTYPE *loc_val = loc_val_;
2163bb78ce7dSAdrian Hunter 
216416fa7e82SJiri Olsa 	return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term,
2165cecf3a2eSJiri Olsa 			config, NULL, num,
2166cecf3a2eSJiri Olsa 			loc_term ? loc_term->first_column : 0,
2167cecf3a2eSJiri Olsa 			loc_val ? loc_val->first_column : 0);
216816fa7e82SJiri Olsa }
216916fa7e82SJiri Olsa 
21706cee6cd3SArnaldo Carvalho de Melo int parse_events_term__str(struct parse_events_term **term,
2171cecf3a2eSJiri Olsa 			   int type_term, char *config, char *str,
2172bb78ce7dSAdrian Hunter 			   void *loc_term_, void *loc_val_)
217316fa7e82SJiri Olsa {
2174bb78ce7dSAdrian Hunter 	YYLTYPE *loc_term = loc_term_;
2175bb78ce7dSAdrian Hunter 	YYLTYPE *loc_val = loc_val_;
2176bb78ce7dSAdrian Hunter 
217716fa7e82SJiri Olsa 	return new_term(term, PARSE_EVENTS__TERM_TYPE_STR, type_term,
2178cecf3a2eSJiri Olsa 			config, str, 0,
2179cecf3a2eSJiri Olsa 			loc_term ? loc_term->first_column : 0,
2180cecf3a2eSJiri Olsa 			loc_val ? loc_val->first_column : 0);
218116fa7e82SJiri Olsa }
218216fa7e82SJiri Olsa 
21836cee6cd3SArnaldo Carvalho de Melo int parse_events_term__sym_hw(struct parse_events_term **term,
21841d33d6dcSJiri Olsa 			      char *config, unsigned idx)
21851d33d6dcSJiri Olsa {
21861d33d6dcSJiri Olsa 	struct event_symbol *sym;
21871d33d6dcSJiri Olsa 
21881d33d6dcSJiri Olsa 	BUG_ON(idx >= PERF_COUNT_HW_MAX);
21891d33d6dcSJiri Olsa 	sym = &event_symbols_hw[idx];
21901d33d6dcSJiri Olsa 
21911d33d6dcSJiri Olsa 	if (config)
21921d33d6dcSJiri Olsa 		return new_term(term, PARSE_EVENTS__TERM_TYPE_STR,
21931d33d6dcSJiri Olsa 				PARSE_EVENTS__TERM_TYPE_USER, config,
2194cecf3a2eSJiri Olsa 				(char *) sym->symbol, 0, 0, 0);
21951d33d6dcSJiri Olsa 	else
21961d33d6dcSJiri Olsa 		return new_term(term, PARSE_EVENTS__TERM_TYPE_STR,
21971d33d6dcSJiri Olsa 				PARSE_EVENTS__TERM_TYPE_USER,
2198cecf3a2eSJiri Olsa 				(char *) "event", (char *) sym->symbol,
2199cecf3a2eSJiri Olsa 				0, 0, 0);
22001d33d6dcSJiri Olsa }
22011d33d6dcSJiri Olsa 
22026cee6cd3SArnaldo Carvalho de Melo int parse_events_term__clone(struct parse_events_term **new,
22036cee6cd3SArnaldo Carvalho de Melo 			     struct parse_events_term *term)
2204a6146d50SZheng Yan {
2205a6146d50SZheng Yan 	return new_term(new, term->type_val, term->type_term, term->config,
2206cecf3a2eSJiri Olsa 			term->val.str, term->val.num,
2207cecf3a2eSJiri Olsa 			term->err_term, term->err_val);
2208a6146d50SZheng Yan }
2209a6146d50SZheng Yan 
2210fc0a2c1dSArnaldo Carvalho de Melo void parse_events_terms__purge(struct list_head *terms)
22118f707d84SJiri Olsa {
22126cee6cd3SArnaldo Carvalho de Melo 	struct parse_events_term *term, *h;
22138f707d84SJiri Olsa 
2214a8adfcebSWang Nan 	list_for_each_entry_safe(term, h, terms, list) {
22152d055bf2SWang Nan 		if (term->array.nr_ranges)
22162d055bf2SWang Nan 			free(term->array.ranges);
2217a8adfcebSWang Nan 		list_del_init(&term->list);
22188f707d84SJiri Olsa 		free(term);
22198f707d84SJiri Olsa 	}
2220a8adfcebSWang Nan }
2221b39b8393SJiri Olsa 
22222146afc6SArnaldo Carvalho de Melo void parse_events_terms__delete(struct list_head *terms)
2223fc0a2c1dSArnaldo Carvalho de Melo {
22242146afc6SArnaldo Carvalho de Melo 	if (!terms)
22252146afc6SArnaldo Carvalho de Melo 		return;
2226fc0a2c1dSArnaldo Carvalho de Melo 	parse_events_terms__purge(terms);
2227d20a5f2bSWang Nan 	free(terms);
2228fc0a2c1dSArnaldo Carvalho de Melo }
2229fc0a2c1dSArnaldo Carvalho de Melo 
22302d055bf2SWang Nan void parse_events__clear_array(struct parse_events_array *a)
22312d055bf2SWang Nan {
22322d055bf2SWang Nan 	free(a->ranges);
22332d055bf2SWang Nan }
22342d055bf2SWang Nan 
2235b39b8393SJiri Olsa void parse_events_evlist_error(struct parse_events_evlist *data,
2236b39b8393SJiri Olsa 			       int idx, const char *str)
2237b39b8393SJiri Olsa {
2238b39b8393SJiri Olsa 	struct parse_events_error *err = data->error;
2239b39b8393SJiri Olsa 
2240a6ced2beSAdrian Hunter 	if (!err)
2241a6ced2beSAdrian Hunter 		return;
2242b39b8393SJiri Olsa 	err->idx = idx;
2243b39b8393SJiri Olsa 	err->str = strdup(str);
2244b39b8393SJiri Olsa 	WARN_ONCE(!err->str, "WARNING: failed to allocate error string");
2245b39b8393SJiri Olsa }
2246ffeb883eSHe Kuang 
224717cb5f84SWang Nan static void config_terms_list(char *buf, size_t buf_sz)
224817cb5f84SWang Nan {
224917cb5f84SWang Nan 	int i;
225017cb5f84SWang Nan 	bool first = true;
225117cb5f84SWang Nan 
225217cb5f84SWang Nan 	buf[0] = '\0';
225317cb5f84SWang Nan 	for (i = 0; i < __PARSE_EVENTS__TERM_TYPE_NR; i++) {
225417cb5f84SWang Nan 		const char *name = config_term_names[i];
225517cb5f84SWang Nan 
22561669e509SWang Nan 		if (!config_term_avail(i, NULL))
22571669e509SWang Nan 			continue;
225817cb5f84SWang Nan 		if (!name)
225917cb5f84SWang Nan 			continue;
226017cb5f84SWang Nan 		if (name[0] == '<')
226117cb5f84SWang Nan 			continue;
226217cb5f84SWang Nan 
226317cb5f84SWang Nan 		if (strlen(buf) + strlen(name) + 2 >= buf_sz)
226417cb5f84SWang Nan 			return;
226517cb5f84SWang Nan 
226617cb5f84SWang Nan 		if (!first)
226717cb5f84SWang Nan 			strcat(buf, ",");
226817cb5f84SWang Nan 		else
226917cb5f84SWang Nan 			first = false;
227017cb5f84SWang Nan 		strcat(buf, name);
227117cb5f84SWang Nan 	}
227217cb5f84SWang Nan }
227317cb5f84SWang Nan 
2274ffeb883eSHe Kuang /*
2275ffeb883eSHe Kuang  * Return string contains valid config terms of an event.
2276ffeb883eSHe Kuang  * @additional_terms: For terms such as PMU sysfs terms.
2277ffeb883eSHe Kuang  */
2278ffeb883eSHe Kuang char *parse_events_formats_error_string(char *additional_terms)
2279ffeb883eSHe Kuang {
2280ffeb883eSHe Kuang 	char *str;
228117cb5f84SWang Nan 	/* "branch_type" is the longest name */
228217cb5f84SWang Nan 	char static_terms[__PARSE_EVENTS__TERM_TYPE_NR *
228317cb5f84SWang Nan 			  (sizeof("branch_type") - 1)];
2284ffeb883eSHe Kuang 
228517cb5f84SWang Nan 	config_terms_list(static_terms, sizeof(static_terms));
2286ffeb883eSHe Kuang 	/* valid terms */
2287ffeb883eSHe Kuang 	if (additional_terms) {
228826dee028SWang Nan 		if (asprintf(&str, "valid terms: %s,%s",
228926dee028SWang Nan 			     additional_terms, static_terms) < 0)
2290ffeb883eSHe Kuang 			goto fail;
2291ffeb883eSHe Kuang 	} else {
229226dee028SWang Nan 		if (asprintf(&str, "valid terms: %s", static_terms) < 0)
2293ffeb883eSHe Kuang 			goto fail;
2294ffeb883eSHe Kuang 	}
2295ffeb883eSHe Kuang 	return str;
2296ffeb883eSHe Kuang 
2297ffeb883eSHe Kuang fail:
2298ffeb883eSHe Kuang 	return NULL;
2299ffeb883eSHe Kuang }
2300