xref: /linux/tools/perf/util/parse-events.c (revision c410431cefefd766266139ed56bca21668e4f9a7)
11b290d67SFrederic Weisbecker #include "../../../include/linux/hw_breakpoint.h"
286470930SIngo Molnar #include "util.h"
36b58e7f1SUlrich Drepper #include "../perf.h"
4361c99a6SArnaldo Carvalho de Melo #include "evlist.h"
569aad6f1SArnaldo Carvalho de Melo #include "evsel.h"
686470930SIngo Molnar #include "parse-options.h"
786470930SIngo Molnar #include "parse-events.h"
886470930SIngo Molnar #include "exec_cmd.h"
986470930SIngo Molnar #include "string.h"
105aab621bSArnaldo Carvalho de Melo #include "symbol.h"
115beeded1SJason Baron #include "cache.h"
128755a8f2SArjan van de Ven #include "header.h"
13549104f2SClark Williams #include "debugfs.h"
1489812fc8SJiri Olsa #include "parse-events-flex.h"
155f537a26SJiri Olsa #include "pmu.h"
1689812fc8SJiri Olsa 
1789812fc8SJiri Olsa #define MAX_NAME_LEN 100
1886470930SIngo Molnar 
1986470930SIngo Molnar struct event_symbol {
209cffa8d5SPaul Mackerras 	u8		type;
219cffa8d5SPaul Mackerras 	u64		config;
2283a0944fSIngo Molnar 	const char	*symbol;
2383a0944fSIngo Molnar 	const char	*alias;
2486470930SIngo Molnar };
2586470930SIngo Molnar 
2682ba1f2fSJiri Olsa #ifdef PARSER_DEBUG
2782ba1f2fSJiri Olsa extern int parse_events_debug;
2882ba1f2fSJiri Olsa #endif
29b847cbdcSJiri Olsa int parse_events_parse(struct list_head *list, int *idx);
30bcd3279fSFrederic Weisbecker 
3151e26842SJaswinder Singh Rajput #define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
3251e26842SJaswinder Singh Rajput #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
3386470930SIngo Molnar 
3486470930SIngo Molnar static struct event_symbol event_symbols[] = {
3574d5b588SJaswinder Singh Rajput   { CHW(CPU_CYCLES),			"cpu-cycles",			"cycles"		},
36129c04cbSIngo Molnar   { CHW(STALLED_CYCLES_FRONTEND),	"stalled-cycles-frontend",	"idle-cycles-frontend"	},
37129c04cbSIngo Molnar   { CHW(STALLED_CYCLES_BACKEND),	"stalled-cycles-backend",	"idle-cycles-backend"	},
3874d5b588SJaswinder Singh Rajput   { CHW(INSTRUCTIONS),			"instructions",			""			},
3974d5b588SJaswinder Singh Rajput   { CHW(CACHE_REFERENCES),		"cache-references",		""			},
4074d5b588SJaswinder Singh Rajput   { CHW(CACHE_MISSES),			"cache-misses",			""			},
4174d5b588SJaswinder Singh Rajput   { CHW(BRANCH_INSTRUCTIONS),		"branch-instructions",		"branches"		},
4274d5b588SJaswinder Singh Rajput   { CHW(BRANCH_MISSES),			"branch-misses",		""			},
4374d5b588SJaswinder Singh Rajput   { CHW(BUS_CYCLES),			"bus-cycles",			""			},
44f1ac18afSStephane Eranian   { CHW(REF_CPU_CYCLES),		"ref-cycles",			""			},
4586470930SIngo Molnar 
4674d5b588SJaswinder Singh Rajput   { CSW(CPU_CLOCK),			"cpu-clock",			""			},
4774d5b588SJaswinder Singh Rajput   { CSW(TASK_CLOCK),			"task-clock",			""			},
48c0c22dbfSJaswinder Singh Rajput   { CSW(PAGE_FAULTS),			"page-faults",			"faults"		},
4974d5b588SJaswinder Singh Rajput   { CSW(PAGE_FAULTS_MIN),		"minor-faults",			""			},
5074d5b588SJaswinder Singh Rajput   { CSW(PAGE_FAULTS_MAJ),		"major-faults",			""			},
5174d5b588SJaswinder Singh Rajput   { CSW(CONTEXT_SWITCHES),		"context-switches",		"cs"			},
5274d5b588SJaswinder Singh Rajput   { CSW(CPU_MIGRATIONS),		"cpu-migrations",		"migrations"		},
53f7d79860SAnton Blanchard   { CSW(ALIGNMENT_FAULTS),		"alignment-faults",		""			},
54f7d79860SAnton Blanchard   { CSW(EMULATION_FAULTS),		"emulation-faults",		""			},
5586470930SIngo Molnar };
5686470930SIngo Molnar 
57cdd6c482SIngo Molnar #define __PERF_EVENT_FIELD(config, name) \
58cdd6c482SIngo Molnar 	((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT)
5986470930SIngo Molnar 
60cdd6c482SIngo Molnar #define PERF_EVENT_RAW(config)		__PERF_EVENT_FIELD(config, RAW)
61cdd6c482SIngo Molnar #define PERF_EVENT_CONFIG(config)	__PERF_EVENT_FIELD(config, CONFIG)
62cdd6c482SIngo Molnar #define PERF_EVENT_TYPE(config)		__PERF_EVENT_FIELD(config, TYPE)
63cdd6c482SIngo Molnar #define PERF_EVENT_ID(config)		__PERF_EVENT_FIELD(config, EVENT)
6486470930SIngo Molnar 
65d3d1e86dSIngo Molnar static const char *sw_event_names[PERF_COUNT_SW_MAX] = {
66749141d9SIngo Molnar 	"cpu-clock",
67749141d9SIngo Molnar 	"task-clock",
6886470930SIngo Molnar 	"page-faults",
6986470930SIngo Molnar 	"context-switches",
7086470930SIngo Molnar 	"CPU-migrations",
7186470930SIngo Molnar 	"minor-faults",
7286470930SIngo Molnar 	"major-faults",
73f7d79860SAnton Blanchard 	"alignment-faults",
74f7d79860SAnton Blanchard 	"emulation-faults",
7586470930SIngo Molnar };
7686470930SIngo Molnar 
7786470930SIngo Molnar #define MAX_ALIASES 8
7886470930SIngo Molnar 
790111919dSJiri Olsa static const char *hw_cache[PERF_COUNT_HW_CACHE_MAX][MAX_ALIASES] = {
809590b7baSAnton Blanchard  { "L1-dcache",	"l1-d",		"l1d",		"L1-data",		},
819590b7baSAnton Blanchard  { "L1-icache",	"l1-i",		"l1i",		"L1-instruction",	},
820111919dSJiri Olsa  { "LLC",	"L2",							},
83e5c59547SJaswinder Singh Rajput  { "dTLB",	"d-tlb",	"Data-TLB",				},
84e5c59547SJaswinder Singh Rajput  { "iTLB",	"i-tlb",	"Instruction-TLB",			},
85e5c59547SJaswinder Singh Rajput  { "branch",	"branches",	"bpu",		"btb",		"bpc",	},
860111919dSJiri Olsa  { "node",								},
8786470930SIngo Molnar };
8886470930SIngo Molnar 
890111919dSJiri Olsa static const char *hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX][MAX_ALIASES] = {
90e5c59547SJaswinder Singh Rajput  { "load",	"loads",	"read",					},
91e5c59547SJaswinder Singh Rajput  { "store",	"stores",	"write",				},
92e5c59547SJaswinder Singh Rajput  { "prefetch",	"prefetches",	"speculative-read", "speculative-load",	},
9386470930SIngo Molnar };
9486470930SIngo Molnar 
950111919dSJiri Olsa static const char *hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
960111919dSJiri Olsa 				  [MAX_ALIASES] = {
97e5c59547SJaswinder Singh Rajput  { "refs",	"Reference",	"ops",		"access",		},
98e5c59547SJaswinder Singh Rajput  { "misses",	"miss",							},
9986470930SIngo Molnar };
10086470930SIngo Molnar 
10106813f6cSJaswinder Singh Rajput #define C(x)		PERF_COUNT_HW_CACHE_##x
10206813f6cSJaswinder Singh Rajput #define CACHE_READ	(1 << C(OP_READ))
10306813f6cSJaswinder Singh Rajput #define CACHE_WRITE	(1 << C(OP_WRITE))
10406813f6cSJaswinder Singh Rajput #define CACHE_PREFETCH	(1 << C(OP_PREFETCH))
10506813f6cSJaswinder Singh Rajput #define COP(x)		(1 << x)
10606813f6cSJaswinder Singh Rajput 
10706813f6cSJaswinder Singh Rajput /*
10806813f6cSJaswinder Singh Rajput  * cache operartion stat
10906813f6cSJaswinder Singh Rajput  * L1I : Read and prefetch only
11006813f6cSJaswinder Singh Rajput  * ITLB and BPU : Read-only
11106813f6cSJaswinder Singh Rajput  */
11206813f6cSJaswinder Singh Rajput static unsigned long hw_cache_stat[C(MAX)] = {
11306813f6cSJaswinder Singh Rajput  [C(L1D)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
11406813f6cSJaswinder Singh Rajput  [C(L1I)]	= (CACHE_READ | CACHE_PREFETCH),
11506813f6cSJaswinder Singh Rajput  [C(LL)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
11606813f6cSJaswinder Singh Rajput  [C(DTLB)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
11706813f6cSJaswinder Singh Rajput  [C(ITLB)]	= (CACHE_READ),
11806813f6cSJaswinder Singh Rajput  [C(BPU)]	= (CACHE_READ),
1190111919dSJiri Olsa  [C(NODE)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
12006813f6cSJaswinder Singh Rajput };
12106813f6cSJaswinder Singh Rajput 
1226b58e7f1SUlrich Drepper #define for_each_subsystem(sys_dir, sys_dirent, sys_next)	       \
123f6bdafefSJason Baron 	while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next)	       \
1246b58e7f1SUlrich Drepper 	if (sys_dirent.d_type == DT_DIR &&				       \
125f6bdafefSJason Baron 	   (strcmp(sys_dirent.d_name, ".")) &&				       \
126f6bdafefSJason Baron 	   (strcmp(sys_dirent.d_name, "..")))
127f6bdafefSJason Baron 
128ae07b63fSPeter Zijlstra static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
129ae07b63fSPeter Zijlstra {
130ae07b63fSPeter Zijlstra 	char evt_path[MAXPATHLEN];
131ae07b63fSPeter Zijlstra 	int fd;
132ae07b63fSPeter Zijlstra 
133ebf294bfSArnaldo Carvalho de Melo 	snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path,
134ae07b63fSPeter Zijlstra 			sys_dir->d_name, evt_dir->d_name);
135ae07b63fSPeter Zijlstra 	fd = open(evt_path, O_RDONLY);
136ae07b63fSPeter Zijlstra 	if (fd < 0)
137ae07b63fSPeter Zijlstra 		return -EINVAL;
138ae07b63fSPeter Zijlstra 	close(fd);
139ae07b63fSPeter Zijlstra 
140ae07b63fSPeter Zijlstra 	return 0;
141ae07b63fSPeter Zijlstra }
142ae07b63fSPeter Zijlstra 
1436b58e7f1SUlrich Drepper #define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next)	       \
144f6bdafefSJason Baron 	while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next)        \
1456b58e7f1SUlrich Drepper 	if (evt_dirent.d_type == DT_DIR &&				       \
146f6bdafefSJason Baron 	   (strcmp(evt_dirent.d_name, ".")) &&				       \
147ae07b63fSPeter Zijlstra 	   (strcmp(evt_dirent.d_name, "..")) &&				       \
148ae07b63fSPeter Zijlstra 	   (!tp_event_has_id(&sys_dirent, &evt_dirent)))
149f6bdafefSJason Baron 
150270bbbe8SLi Zefan #define MAX_EVENT_LENGTH 512
151f6bdafefSJason Baron 
152f6bdafefSJason Baron 
1531ef2ed10SFrederic Weisbecker struct tracepoint_path *tracepoint_id_to_path(u64 config)
154f6bdafefSJason Baron {
1551ef2ed10SFrederic Weisbecker 	struct tracepoint_path *path = NULL;
156f6bdafefSJason Baron 	DIR *sys_dir, *evt_dir;
157f6bdafefSJason Baron 	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
1588aa8a7c8SStephane Eranian 	char id_buf[24];
159725b1368SEric Dumazet 	int fd;
160f6bdafefSJason Baron 	u64 id;
161f6bdafefSJason Baron 	char evt_path[MAXPATHLEN];
162725b1368SEric Dumazet 	char dir_path[MAXPATHLEN];
163f6bdafefSJason Baron 
164ebf294bfSArnaldo Carvalho de Melo 	if (debugfs_valid_mountpoint(tracing_events_path))
1651ef2ed10SFrederic Weisbecker 		return NULL;
166f6bdafefSJason Baron 
167ebf294bfSArnaldo Carvalho de Melo 	sys_dir = opendir(tracing_events_path);
168f6bdafefSJason Baron 	if (!sys_dir)
169725b1368SEric Dumazet 		return NULL;
170f6bdafefSJason Baron 
1716b58e7f1SUlrich Drepper 	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
172725b1368SEric Dumazet 
173ebf294bfSArnaldo Carvalho de Melo 		snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
174725b1368SEric Dumazet 			 sys_dirent.d_name);
175725b1368SEric Dumazet 		evt_dir = opendir(dir_path);
176725b1368SEric Dumazet 		if (!evt_dir)
1776b58e7f1SUlrich Drepper 			continue;
178725b1368SEric Dumazet 
1796b58e7f1SUlrich Drepper 		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
180725b1368SEric Dumazet 
181725b1368SEric Dumazet 			snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
182f6bdafefSJason Baron 				 evt_dirent.d_name);
183725b1368SEric Dumazet 			fd = open(evt_path, O_RDONLY);
184f6bdafefSJason Baron 			if (fd < 0)
185f6bdafefSJason Baron 				continue;
186f6bdafefSJason Baron 			if (read(fd, id_buf, sizeof(id_buf)) < 0) {
187f6bdafefSJason Baron 				close(fd);
188f6bdafefSJason Baron 				continue;
189f6bdafefSJason Baron 			}
190f6bdafefSJason Baron 			close(fd);
191f6bdafefSJason Baron 			id = atoll(id_buf);
192f6bdafefSJason Baron 			if (id == config) {
193f6bdafefSJason Baron 				closedir(evt_dir);
194f6bdafefSJason Baron 				closedir(sys_dir);
19559b4caebSJulia Lawall 				path = zalloc(sizeof(*path));
1961ef2ed10SFrederic Weisbecker 				path->system = malloc(MAX_EVENT_LENGTH);
1971ef2ed10SFrederic Weisbecker 				if (!path->system) {
1981ef2ed10SFrederic Weisbecker 					free(path);
1991ef2ed10SFrederic Weisbecker 					return NULL;
2001ef2ed10SFrederic Weisbecker 				}
2011ef2ed10SFrederic Weisbecker 				path->name = malloc(MAX_EVENT_LENGTH);
2021ef2ed10SFrederic Weisbecker 				if (!path->name) {
2031ef2ed10SFrederic Weisbecker 					free(path->system);
2041ef2ed10SFrederic Weisbecker 					free(path);
2051ef2ed10SFrederic Weisbecker 					return NULL;
2061ef2ed10SFrederic Weisbecker 				}
2071ef2ed10SFrederic Weisbecker 				strncpy(path->system, sys_dirent.d_name,
2081ef2ed10SFrederic Weisbecker 					MAX_EVENT_LENGTH);
2091ef2ed10SFrederic Weisbecker 				strncpy(path->name, evt_dirent.d_name,
2101ef2ed10SFrederic Weisbecker 					MAX_EVENT_LENGTH);
2111ef2ed10SFrederic Weisbecker 				return path;
212f6bdafefSJason Baron 			}
213f6bdafefSJason Baron 		}
214f6bdafefSJason Baron 		closedir(evt_dir);
215f6bdafefSJason Baron 	}
216f6bdafefSJason Baron 
217f6bdafefSJason Baron 	closedir(sys_dir);
2181ef2ed10SFrederic Weisbecker 	return NULL;
2191ef2ed10SFrederic Weisbecker }
2201ef2ed10SFrederic Weisbecker 
2211ef2ed10SFrederic Weisbecker #define TP_PATH_LEN (MAX_EVENT_LENGTH * 2 + 1)
2221ef2ed10SFrederic Weisbecker static const char *tracepoint_id_to_name(u64 config)
2231ef2ed10SFrederic Weisbecker {
2241ef2ed10SFrederic Weisbecker 	static char buf[TP_PATH_LEN];
2251ef2ed10SFrederic Weisbecker 	struct tracepoint_path *path;
2261ef2ed10SFrederic Weisbecker 
2271ef2ed10SFrederic Weisbecker 	path = tracepoint_id_to_path(config);
2281ef2ed10SFrederic Weisbecker 	if (path) {
2291ef2ed10SFrederic Weisbecker 		snprintf(buf, TP_PATH_LEN, "%s:%s", path->system, path->name);
2301ef2ed10SFrederic Weisbecker 		free(path->name);
2311ef2ed10SFrederic Weisbecker 		free(path->system);
2321ef2ed10SFrederic Weisbecker 		free(path);
2331ef2ed10SFrederic Weisbecker 	} else
2341ef2ed10SFrederic Weisbecker 		snprintf(buf, TP_PATH_LEN, "%s:%s", "unknown", "unknown");
2351ef2ed10SFrederic Weisbecker 
2361ef2ed10SFrederic Weisbecker 	return buf;
237f6bdafefSJason Baron }
238f6bdafefSJason Baron 
23906813f6cSJaswinder Singh Rajput static int is_cache_op_valid(u8 cache_type, u8 cache_op)
24006813f6cSJaswinder Singh Rajput {
24106813f6cSJaswinder Singh Rajput 	if (hw_cache_stat[cache_type] & COP(cache_op))
24206813f6cSJaswinder Singh Rajput 		return 1;	/* valid */
24306813f6cSJaswinder Singh Rajput 	else
24406813f6cSJaswinder Singh Rajput 		return 0;	/* invalid */
24506813f6cSJaswinder Singh Rajput }
24606813f6cSJaswinder Singh Rajput 
247e5c59547SJaswinder Singh Rajput static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
248e5c59547SJaswinder Singh Rajput {
249e5c59547SJaswinder Singh Rajput 	static char name[50];
250e5c59547SJaswinder Singh Rajput 
251e5c59547SJaswinder Singh Rajput 	if (cache_result) {
252e5c59547SJaswinder Singh Rajput 		sprintf(name, "%s-%s-%s", hw_cache[cache_type][0],
253e5c59547SJaswinder Singh Rajput 			hw_cache_op[cache_op][0],
254e5c59547SJaswinder Singh Rajput 			hw_cache_result[cache_result][0]);
255e5c59547SJaswinder Singh Rajput 	} else {
256e5c59547SJaswinder Singh Rajput 		sprintf(name, "%s-%s", hw_cache[cache_type][0],
257e5c59547SJaswinder Singh Rajput 			hw_cache_op[cache_op][1]);
258e5c59547SJaswinder Singh Rajput 	}
259e5c59547SJaswinder Singh Rajput 
260e5c59547SJaswinder Singh Rajput 	return name;
261e5c59547SJaswinder Singh Rajput }
262e5c59547SJaswinder Singh Rajput 
2631424dc96SDavid Ahern const char *event_type(int type)
2641424dc96SDavid Ahern {
2651424dc96SDavid Ahern 	switch (type) {
2661424dc96SDavid Ahern 	case PERF_TYPE_HARDWARE:
2671424dc96SDavid Ahern 		return "hardware";
2681424dc96SDavid Ahern 
2691424dc96SDavid Ahern 	case PERF_TYPE_SOFTWARE:
2701424dc96SDavid Ahern 		return "software";
2711424dc96SDavid Ahern 
2721424dc96SDavid Ahern 	case PERF_TYPE_TRACEPOINT:
2731424dc96SDavid Ahern 		return "tracepoint";
2741424dc96SDavid Ahern 
2751424dc96SDavid Ahern 	case PERF_TYPE_HW_CACHE:
2761424dc96SDavid Ahern 		return "hardware-cache";
2771424dc96SDavid Ahern 
2781424dc96SDavid Ahern 	default:
2791424dc96SDavid Ahern 		break;
2801424dc96SDavid Ahern 	}
2811424dc96SDavid Ahern 
2821424dc96SDavid Ahern 	return "unknown";
2831424dc96SDavid Ahern }
2841424dc96SDavid Ahern 
28569aad6f1SArnaldo Carvalho de Melo const char *event_name(struct perf_evsel *evsel)
28686470930SIngo Molnar {
28769aad6f1SArnaldo Carvalho de Melo 	u64 config = evsel->attr.config;
28869aad6f1SArnaldo Carvalho de Melo 	int type = evsel->attr.type;
2898f18aec5SPeter Zijlstra 
290*c410431cSArnaldo Carvalho de Melo 	if (type == PERF_TYPE_RAW || type == PERF_TYPE_HARDWARE) {
291*c410431cSArnaldo Carvalho de Melo 		/*
292*c410431cSArnaldo Carvalho de Melo  		 * XXX minimal fix, see comment on perf_evsen__name, this static buffer
293*c410431cSArnaldo Carvalho de Melo  		 * will go away together with event_name in the next devel cycle.
294*c410431cSArnaldo Carvalho de Melo  		 */
295*c410431cSArnaldo Carvalho de Melo 		static char bf[128];
296*c410431cSArnaldo Carvalho de Melo 		perf_evsel__name(evsel, bf, sizeof(bf));
297*c410431cSArnaldo Carvalho de Melo 		return bf;
298*c410431cSArnaldo Carvalho de Melo 	}
299*c410431cSArnaldo Carvalho de Melo 
300f0c55bcfSStephane Eranian 	if (evsel->name)
301f0c55bcfSStephane Eranian 		return evsel->name;
302f0c55bcfSStephane Eranian 
3038f18aec5SPeter Zijlstra 	return __event_name(type, config);
3048f18aec5SPeter Zijlstra }
3058f18aec5SPeter Zijlstra 
30683a0944fSIngo Molnar const char *__event_name(int type, u64 config)
3078f18aec5SPeter Zijlstra {
30886470930SIngo Molnar 	static char buf[32];
30986470930SIngo Molnar 
3108f18aec5SPeter Zijlstra 	if (type == PERF_TYPE_RAW) {
3119486aa38SArnaldo Carvalho de Melo 		sprintf(buf, "raw 0x%" PRIx64, config);
31286470930SIngo Molnar 		return buf;
31386470930SIngo Molnar 	}
31486470930SIngo Molnar 
31586470930SIngo Molnar 	switch (type) {
31686470930SIngo Molnar 	case PERF_TYPE_HARDWARE:
317*c410431cSArnaldo Carvalho de Melo 		return __perf_evsel__hw_name(config);
31886470930SIngo Molnar 
31986470930SIngo Molnar 	case PERF_TYPE_HW_CACHE: {
3209cffa8d5SPaul Mackerras 		u8 cache_type, cache_op, cache_result;
32186470930SIngo Molnar 
32286470930SIngo Molnar 		cache_type   = (config >>  0) & 0xff;
32386470930SIngo Molnar 		if (cache_type > PERF_COUNT_HW_CACHE_MAX)
32486470930SIngo Molnar 			return "unknown-ext-hardware-cache-type";
32586470930SIngo Molnar 
32686470930SIngo Molnar 		cache_op     = (config >>  8) & 0xff;
32786470930SIngo Molnar 		if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX)
32886470930SIngo Molnar 			return "unknown-ext-hardware-cache-op";
32986470930SIngo Molnar 
33086470930SIngo Molnar 		cache_result = (config >> 16) & 0xff;
33186470930SIngo Molnar 		if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX)
33286470930SIngo Molnar 			return "unknown-ext-hardware-cache-result";
33386470930SIngo Molnar 
33406813f6cSJaswinder Singh Rajput 		if (!is_cache_op_valid(cache_type, cache_op))
33506813f6cSJaswinder Singh Rajput 			return "invalid-cache";
33686470930SIngo Molnar 
337e5c59547SJaswinder Singh Rajput 		return event_cache_name(cache_type, cache_op, cache_result);
33886470930SIngo Molnar 	}
33986470930SIngo Molnar 
34086470930SIngo Molnar 	case PERF_TYPE_SOFTWARE:
3411fc570adSIngo Molnar 		if (config < PERF_COUNT_SW_MAX && sw_event_names[config])
34286470930SIngo Molnar 			return sw_event_names[config];
34386470930SIngo Molnar 		return "unknown-software";
34486470930SIngo Molnar 
345f6bdafefSJason Baron 	case PERF_TYPE_TRACEPOINT:
346f6bdafefSJason Baron 		return tracepoint_id_to_name(config);
347f6bdafefSJason Baron 
34886470930SIngo Molnar 	default:
34986470930SIngo Molnar 		break;
35086470930SIngo Molnar 	}
35186470930SIngo Molnar 
35286470930SIngo Molnar 	return "unknown";
35386470930SIngo Molnar }
35486470930SIngo Molnar 
355b847cbdcSJiri Olsa static int add_event(struct list_head **_list, int *idx,
35689812fc8SJiri Olsa 		     struct perf_event_attr *attr, char *name)
35789812fc8SJiri Olsa {
35889812fc8SJiri Olsa 	struct perf_evsel *evsel;
359b847cbdcSJiri Olsa 	struct list_head *list = *_list;
360b847cbdcSJiri Olsa 
361b847cbdcSJiri Olsa 	if (!list) {
362b847cbdcSJiri Olsa 		list = malloc(sizeof(*list));
363b847cbdcSJiri Olsa 		if (!list)
364b847cbdcSJiri Olsa 			return -ENOMEM;
365b847cbdcSJiri Olsa 		INIT_LIST_HEAD(list);
366b847cbdcSJiri Olsa 	}
36789812fc8SJiri Olsa 
36889812fc8SJiri Olsa 	event_attr_init(attr);
36989812fc8SJiri Olsa 
37089812fc8SJiri Olsa 	evsel = perf_evsel__new(attr, (*idx)++);
371b847cbdcSJiri Olsa 	if (!evsel) {
372b847cbdcSJiri Olsa 		free(list);
37389812fc8SJiri Olsa 		return -ENOMEM;
374b847cbdcSJiri Olsa 	}
37589812fc8SJiri Olsa 
37689812fc8SJiri Olsa 	evsel->name = strdup(name);
377b847cbdcSJiri Olsa 	list_add_tail(&evsel->node, list);
378b847cbdcSJiri Olsa 	*_list = list;
37989812fc8SJiri Olsa 	return 0;
38089812fc8SJiri Olsa }
38189812fc8SJiri Olsa 
38289812fc8SJiri Olsa static int parse_aliases(char *str, const char *names[][MAX_ALIASES], int size)
38386470930SIngo Molnar {
38486470930SIngo Molnar 	int i, j;
38561c45981SPaul Mackerras 	int n, longest = -1;
38686470930SIngo Molnar 
38786470930SIngo Molnar 	for (i = 0; i < size; i++) {
38861c45981SPaul Mackerras 		for (j = 0; j < MAX_ALIASES && names[i][j]; j++) {
38961c45981SPaul Mackerras 			n = strlen(names[i][j]);
39089812fc8SJiri Olsa 			if (n > longest && !strncasecmp(str, names[i][j], n))
39161c45981SPaul Mackerras 				longest = n;
39261c45981SPaul Mackerras 		}
39389812fc8SJiri Olsa 		if (longest > 0)
39486470930SIngo Molnar 			return i;
39586470930SIngo Molnar 	}
39686470930SIngo Molnar 
3978953645fSIngo Molnar 	return -1;
39886470930SIngo Molnar }
39986470930SIngo Molnar 
400b847cbdcSJiri Olsa int parse_events_add_cache(struct list_head **list, int *idx,
40189812fc8SJiri Olsa 			   char *type, char *op_result1, char *op_result2)
40286470930SIngo Molnar {
40389812fc8SJiri Olsa 	struct perf_event_attr attr;
40489812fc8SJiri Olsa 	char name[MAX_NAME_LEN];
40561c45981SPaul Mackerras 	int cache_type = -1, cache_op = -1, cache_result = -1;
40689812fc8SJiri Olsa 	char *op_result[2] = { op_result1, op_result2 };
40789812fc8SJiri Olsa 	int i, n;
40886470930SIngo Molnar 
40986470930SIngo Molnar 	/*
41086470930SIngo Molnar 	 * No fallback - if we cannot get a clear cache type
41186470930SIngo Molnar 	 * then bail out:
41286470930SIngo Molnar 	 */
41389812fc8SJiri Olsa 	cache_type = parse_aliases(type, hw_cache,
41489812fc8SJiri Olsa 				   PERF_COUNT_HW_CACHE_MAX);
41586470930SIngo Molnar 	if (cache_type == -1)
41689812fc8SJiri Olsa 		return -EINVAL;
41786470930SIngo Molnar 
41889812fc8SJiri Olsa 	n = snprintf(name, MAX_NAME_LEN, "%s", type);
41989812fc8SJiri Olsa 
42089812fc8SJiri Olsa 	for (i = 0; (i < 2) && (op_result[i]); i++) {
42189812fc8SJiri Olsa 		char *str = op_result[i];
42289812fc8SJiri Olsa 
42389812fc8SJiri Olsa 		snprintf(name + n, MAX_NAME_LEN - n, "-%s\n", str);
42461c45981SPaul Mackerras 
42561c45981SPaul Mackerras 		if (cache_op == -1) {
42689812fc8SJiri Olsa 			cache_op = parse_aliases(str, hw_cache_op,
42761c45981SPaul Mackerras 						 PERF_COUNT_HW_CACHE_OP_MAX);
42861c45981SPaul Mackerras 			if (cache_op >= 0) {
42961c45981SPaul Mackerras 				if (!is_cache_op_valid(cache_type, cache_op))
43089812fc8SJiri Olsa 					return -EINVAL;
43161c45981SPaul Mackerras 				continue;
43261c45981SPaul Mackerras 			}
43361c45981SPaul Mackerras 		}
43461c45981SPaul Mackerras 
43561c45981SPaul Mackerras 		if (cache_result == -1) {
43689812fc8SJiri Olsa 			cache_result = parse_aliases(str, hw_cache_result,
43761c45981SPaul Mackerras 						PERF_COUNT_HW_CACHE_RESULT_MAX);
43861c45981SPaul Mackerras 			if (cache_result >= 0)
43961c45981SPaul Mackerras 				continue;
44061c45981SPaul Mackerras 		}
44161c45981SPaul Mackerras 	}
44261c45981SPaul Mackerras 
44386470930SIngo Molnar 	/*
44486470930SIngo Molnar 	 * Fall back to reads:
44586470930SIngo Molnar 	 */
4468953645fSIngo Molnar 	if (cache_op == -1)
4478953645fSIngo Molnar 		cache_op = PERF_COUNT_HW_CACHE_OP_READ;
44886470930SIngo Molnar 
44986470930SIngo Molnar 	/*
45086470930SIngo Molnar 	 * Fall back to accesses:
45186470930SIngo Molnar 	 */
45286470930SIngo Molnar 	if (cache_result == -1)
45386470930SIngo Molnar 		cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS;
45486470930SIngo Molnar 
45589812fc8SJiri Olsa 	memset(&attr, 0, sizeof(attr));
45689812fc8SJiri Olsa 	attr.config = cache_type | (cache_op << 8) | (cache_result << 16);
45789812fc8SJiri Olsa 	attr.type = PERF_TYPE_HW_CACHE;
45889812fc8SJiri Olsa 	return add_event(list, idx, &attr, name);
45986470930SIngo Molnar }
46086470930SIngo Molnar 
461b847cbdcSJiri Olsa static int add_tracepoint(struct list_head **list, int *idx,
46289812fc8SJiri Olsa 			  char *sys_name, char *evt_name)
463bcd3279fSFrederic Weisbecker {
46489812fc8SJiri Olsa 	struct perf_event_attr attr;
46589812fc8SJiri Olsa 	char name[MAX_NAME_LEN];
466bcd3279fSFrederic Weisbecker 	char evt_path[MAXPATHLEN];
467bcd3279fSFrederic Weisbecker 	char id_buf[4];
468bcd3279fSFrederic Weisbecker 	u64 id;
469bcd3279fSFrederic Weisbecker 	int fd;
470bcd3279fSFrederic Weisbecker 
471ebf294bfSArnaldo Carvalho de Melo 	snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path,
472bcd3279fSFrederic Weisbecker 		 sys_name, evt_name);
473bcd3279fSFrederic Weisbecker 
474bcd3279fSFrederic Weisbecker 	fd = open(evt_path, O_RDONLY);
475bcd3279fSFrederic Weisbecker 	if (fd < 0)
47689812fc8SJiri Olsa 		return -1;
477bcd3279fSFrederic Weisbecker 
478bcd3279fSFrederic Weisbecker 	if (read(fd, id_buf, sizeof(id_buf)) < 0) {
479bcd3279fSFrederic Weisbecker 		close(fd);
48089812fc8SJiri Olsa 		return -1;
481bcd3279fSFrederic Weisbecker 	}
482bcd3279fSFrederic Weisbecker 
483bcd3279fSFrederic Weisbecker 	close(fd);
484bcd3279fSFrederic Weisbecker 	id = atoll(id_buf);
485bcd3279fSFrederic Weisbecker 
48689812fc8SJiri Olsa 	memset(&attr, 0, sizeof(attr));
48789812fc8SJiri Olsa 	attr.config = id;
48889812fc8SJiri Olsa 	attr.type = PERF_TYPE_TRACEPOINT;
48989812fc8SJiri Olsa 	attr.sample_type |= PERF_SAMPLE_RAW;
49089812fc8SJiri Olsa 	attr.sample_type |= PERF_SAMPLE_TIME;
49189812fc8SJiri Olsa 	attr.sample_type |= PERF_SAMPLE_CPU;
49289812fc8SJiri Olsa 	attr.sample_period = 1;
4935710fcadSStephane Eranian 
49489812fc8SJiri Olsa 	snprintf(name, MAX_NAME_LEN, "%s:%s", sys_name, evt_name);
49589812fc8SJiri Olsa 	return add_event(list, idx, &attr, name);
496bcd3279fSFrederic Weisbecker }
497bcd3279fSFrederic Weisbecker 
498b847cbdcSJiri Olsa static int add_tracepoint_multi(struct list_head **list, int *idx,
49989812fc8SJiri Olsa 				char *sys_name, char *evt_name)
500bcd3279fSFrederic Weisbecker {
501bcd3279fSFrederic Weisbecker 	char evt_path[MAXPATHLEN];
502bcd3279fSFrederic Weisbecker 	struct dirent *evt_ent;
503bcd3279fSFrederic Weisbecker 	DIR *evt_dir;
50489812fc8SJiri Olsa 	int ret = 0;
505bcd3279fSFrederic Weisbecker 
506ebf294bfSArnaldo Carvalho de Melo 	snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name);
507bcd3279fSFrederic Weisbecker 	evt_dir = opendir(evt_path);
508bcd3279fSFrederic Weisbecker 	if (!evt_dir) {
509bcd3279fSFrederic Weisbecker 		perror("Can't open event dir");
51089812fc8SJiri Olsa 		return -1;
511bcd3279fSFrederic Weisbecker 	}
512bcd3279fSFrederic Weisbecker 
51389812fc8SJiri Olsa 	while (!ret && (evt_ent = readdir(evt_dir))) {
514bcd3279fSFrederic Weisbecker 		if (!strcmp(evt_ent->d_name, ".")
515bcd3279fSFrederic Weisbecker 		    || !strcmp(evt_ent->d_name, "..")
516bcd3279fSFrederic Weisbecker 		    || !strcmp(evt_ent->d_name, "enable")
517bcd3279fSFrederic Weisbecker 		    || !strcmp(evt_ent->d_name, "filter"))
518bcd3279fSFrederic Weisbecker 			continue;
519bcd3279fSFrederic Weisbecker 
52089812fc8SJiri Olsa 		if (!strglobmatch(evt_ent->d_name, evt_name))
521fb1d2edfSMasami Hiramatsu 			continue;
522fb1d2edfSMasami Hiramatsu 
52389812fc8SJiri Olsa 		ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name);
524bcd3279fSFrederic Weisbecker 	}
525bcd3279fSFrederic Weisbecker 
52689812fc8SJiri Olsa 	return ret;
527bcd3279fSFrederic Weisbecker }
528bcd3279fSFrederic Weisbecker 
529b847cbdcSJiri Olsa int parse_events_add_tracepoint(struct list_head **list, int *idx,
53089812fc8SJiri Olsa 				char *sys, char *event)
531f6bdafefSJason Baron {
53289812fc8SJiri Olsa 	int ret;
533f6bdafefSJason Baron 
53489812fc8SJiri Olsa 	ret = debugfs_valid_mountpoint(tracing_events_path);
53589812fc8SJiri Olsa 	if (ret)
53689812fc8SJiri Olsa 		return ret;
537f6bdafefSJason Baron 
53889812fc8SJiri Olsa 	return strpbrk(event, "*?") ?
53989812fc8SJiri Olsa 	       add_tracepoint_multi(list, idx, sys, event) :
54089812fc8SJiri Olsa 	       add_tracepoint(list, idx, sys, event);
5413a9f131fSFrederic Weisbecker }
5423a9f131fSFrederic Weisbecker 
54389812fc8SJiri Olsa static int
54489812fc8SJiri Olsa parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
5451b290d67SFrederic Weisbecker {
5461b290d67SFrederic Weisbecker 	int i;
5471b290d67SFrederic Weisbecker 
5481b290d67SFrederic Weisbecker 	for (i = 0; i < 3; i++) {
54989812fc8SJiri Olsa 		if (!type || !type[i])
5501b290d67SFrederic Weisbecker 			break;
5511b290d67SFrederic Weisbecker 
5521b290d67SFrederic Weisbecker 		switch (type[i]) {
5531b290d67SFrederic Weisbecker 		case 'r':
5541b290d67SFrederic Weisbecker 			attr->bp_type |= HW_BREAKPOINT_R;
5551b290d67SFrederic Weisbecker 			break;
5561b290d67SFrederic Weisbecker 		case 'w':
5571b290d67SFrederic Weisbecker 			attr->bp_type |= HW_BREAKPOINT_W;
5581b290d67SFrederic Weisbecker 			break;
5591b290d67SFrederic Weisbecker 		case 'x':
5601b290d67SFrederic Weisbecker 			attr->bp_type |= HW_BREAKPOINT_X;
5611b290d67SFrederic Weisbecker 			break;
5621b290d67SFrederic Weisbecker 		default:
56389812fc8SJiri Olsa 			return -EINVAL;
5641b290d67SFrederic Weisbecker 		}
5651b290d67SFrederic Weisbecker 	}
56689812fc8SJiri Olsa 
5671b290d67SFrederic Weisbecker 	if (!attr->bp_type) /* Default */
5681b290d67SFrederic Weisbecker 		attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
5691b290d67SFrederic Weisbecker 
57089812fc8SJiri Olsa 	return 0;
5711b290d67SFrederic Weisbecker }
5721b290d67SFrederic Weisbecker 
573b847cbdcSJiri Olsa int parse_events_add_breakpoint(struct list_head **list, int *idx,
57489812fc8SJiri Olsa 				void *ptr, char *type)
5751b290d67SFrederic Weisbecker {
57689812fc8SJiri Olsa 	struct perf_event_attr attr;
57789812fc8SJiri Olsa 	char name[MAX_NAME_LEN];
5781b290d67SFrederic Weisbecker 
57989812fc8SJiri Olsa 	memset(&attr, 0, sizeof(attr));
5809fafd98fSJiri Olsa 	attr.bp_addr = (unsigned long) ptr;
5811b290d67SFrederic Weisbecker 
58289812fc8SJiri Olsa 	if (parse_breakpoint_type(type, &attr))
58389812fc8SJiri Olsa 		return -EINVAL;
5841b290d67SFrederic Weisbecker 
585aa59a485SFrederic Weisbecker 	/*
586aa59a485SFrederic Weisbecker 	 * We should find a nice way to override the access length
587aa59a485SFrederic Weisbecker 	 * Provide some defaults for now
588aa59a485SFrederic Weisbecker 	 */
58989812fc8SJiri Olsa 	if (attr.bp_type == HW_BREAKPOINT_X)
59089812fc8SJiri Olsa 		attr.bp_len = sizeof(long);
591aa59a485SFrederic Weisbecker 	else
59289812fc8SJiri Olsa 		attr.bp_len = HW_BREAKPOINT_LEN_4;
593aa59a485SFrederic Weisbecker 
59489812fc8SJiri Olsa 	attr.type = PERF_TYPE_BREAKPOINT;
5951b290d67SFrederic Weisbecker 
59689812fc8SJiri Olsa 	snprintf(name, MAX_NAME_LEN, "mem:%p:%s", ptr, type ? type : "rw");
59789812fc8SJiri Olsa 	return add_event(list, idx, &attr, name);
5981b290d67SFrederic Weisbecker }
5991b290d67SFrederic Weisbecker 
6008f707d84SJiri Olsa static int config_term(struct perf_event_attr *attr,
6018f707d84SJiri Olsa 		       struct parse_events__term *term)
6028f707d84SJiri Olsa {
60316fa7e82SJiri Olsa #define CHECK_TYPE_VAL(type)					\
60416fa7e82SJiri Olsa do {								\
60516fa7e82SJiri Olsa 	if (PARSE_EVENTS__TERM_TYPE_ ## type != term->type_val)	\
60616fa7e82SJiri Olsa 		return -EINVAL;					\
60716fa7e82SJiri Olsa } while (0)
60816fa7e82SJiri Olsa 
60916fa7e82SJiri Olsa 	switch (term->type_term) {
6108f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_CONFIG:
61116fa7e82SJiri Olsa 		CHECK_TYPE_VAL(NUM);
6128f707d84SJiri Olsa 		attr->config = term->val.num;
6138f707d84SJiri Olsa 		break;
6148f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_CONFIG1:
61516fa7e82SJiri Olsa 		CHECK_TYPE_VAL(NUM);
6168f707d84SJiri Olsa 		attr->config1 = term->val.num;
6178f707d84SJiri Olsa 		break;
6188f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_CONFIG2:
61916fa7e82SJiri Olsa 		CHECK_TYPE_VAL(NUM);
6208f707d84SJiri Olsa 		attr->config2 = term->val.num;
6218f707d84SJiri Olsa 		break;
6228f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
62316fa7e82SJiri Olsa 		CHECK_TYPE_VAL(NUM);
6248f707d84SJiri Olsa 		attr->sample_period = term->val.num;
6258f707d84SJiri Olsa 		break;
6268f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE:
6278f707d84SJiri Olsa 		/*
6288f707d84SJiri Olsa 		 * TODO uncomment when the field is available
6298f707d84SJiri Olsa 		 * attr->branch_sample_type = term->val.num;
6308f707d84SJiri Olsa 		 */
6318f707d84SJiri Olsa 		break;
6326b5fc39bSJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_NAME:
6336b5fc39bSJiri Olsa 		CHECK_TYPE_VAL(STR);
6346b5fc39bSJiri Olsa 		break;
6358f707d84SJiri Olsa 	default:
6368f707d84SJiri Olsa 		return -EINVAL;
6378f707d84SJiri Olsa 	}
63816fa7e82SJiri Olsa 
6398f707d84SJiri Olsa 	return 0;
64016fa7e82SJiri Olsa #undef CHECK_TYPE_VAL
6418f707d84SJiri Olsa }
6428f707d84SJiri Olsa 
6438f707d84SJiri Olsa static int config_attr(struct perf_event_attr *attr,
6448f707d84SJiri Olsa 		       struct list_head *head, int fail)
6458f707d84SJiri Olsa {
6468f707d84SJiri Olsa 	struct parse_events__term *term;
6478f707d84SJiri Olsa 
6488f707d84SJiri Olsa 	list_for_each_entry(term, head, list)
6498f707d84SJiri Olsa 		if (config_term(attr, term) && fail)
6508f707d84SJiri Olsa 			return -EINVAL;
6518f707d84SJiri Olsa 
6528f707d84SJiri Olsa 	return 0;
6538f707d84SJiri Olsa }
6548f707d84SJiri Olsa 
655b847cbdcSJiri Olsa int parse_events_add_numeric(struct list_head **list, int *idx,
6568f707d84SJiri Olsa 			     unsigned long type, unsigned long config,
6578f707d84SJiri Olsa 			     struct list_head *head_config)
65874d5b588SJaswinder Singh Rajput {
65989812fc8SJiri Olsa 	struct perf_event_attr attr;
66074d5b588SJaswinder Singh Rajput 
66189812fc8SJiri Olsa 	memset(&attr, 0, sizeof(attr));
66289812fc8SJiri Olsa 	attr.type = type;
66389812fc8SJiri Olsa 	attr.config = config;
6648f707d84SJiri Olsa 
6658f707d84SJiri Olsa 	if (head_config &&
6668f707d84SJiri Olsa 	    config_attr(&attr, head_config, 1))
6678f707d84SJiri Olsa 		return -EINVAL;
6688f707d84SJiri Olsa 
66989812fc8SJiri Olsa 	return add_event(list, idx, &attr,
67089812fc8SJiri Olsa 			 (char *) __event_name(type, config));
671b908debdSIngo Molnar }
672b908debdSIngo Molnar 
6736b5fc39bSJiri Olsa static int parse_events__is_name_term(struct parse_events__term *term)
6746b5fc39bSJiri Olsa {
6756b5fc39bSJiri Olsa 	return term->type_term == PARSE_EVENTS__TERM_TYPE_NAME;
6766b5fc39bSJiri Olsa }
6776b5fc39bSJiri Olsa 
6786b5fc39bSJiri Olsa static char *pmu_event_name(struct perf_event_attr *attr,
6796b5fc39bSJiri Olsa 			    struct list_head *head_terms)
6806b5fc39bSJiri Olsa {
6816b5fc39bSJiri Olsa 	struct parse_events__term *term;
6826b5fc39bSJiri Olsa 
6836b5fc39bSJiri Olsa 	list_for_each_entry(term, head_terms, list)
6846b5fc39bSJiri Olsa 		if (parse_events__is_name_term(term))
6856b5fc39bSJiri Olsa 			return term->val.str;
6866b5fc39bSJiri Olsa 
6876b5fc39bSJiri Olsa 	return (char *) __event_name(PERF_TYPE_RAW, attr->config);
6886b5fc39bSJiri Olsa }
6896b5fc39bSJiri Olsa 
690b847cbdcSJiri Olsa int parse_events_add_pmu(struct list_head **list, int *idx,
6915f537a26SJiri Olsa 			 char *name, struct list_head *head_config)
6925f537a26SJiri Olsa {
6935f537a26SJiri Olsa 	struct perf_event_attr attr;
6945f537a26SJiri Olsa 	struct perf_pmu *pmu;
6955f537a26SJiri Olsa 
6965f537a26SJiri Olsa 	pmu = perf_pmu__find(name);
6975f537a26SJiri Olsa 	if (!pmu)
6985f537a26SJiri Olsa 		return -EINVAL;
6995f537a26SJiri Olsa 
7005f537a26SJiri Olsa 	memset(&attr, 0, sizeof(attr));
7015f537a26SJiri Olsa 
7025f537a26SJiri Olsa 	/*
7035f537a26SJiri Olsa 	 * Configure hardcoded terms first, no need to check
7045f537a26SJiri Olsa 	 * return value when called with fail == 0 ;)
7055f537a26SJiri Olsa 	 */
7065f537a26SJiri Olsa 	config_attr(&attr, head_config, 0);
7075f537a26SJiri Olsa 
7085f537a26SJiri Olsa 	if (perf_pmu__config(pmu, &attr, head_config))
7095f537a26SJiri Olsa 		return -EINVAL;
7105f537a26SJiri Olsa 
7116b5fc39bSJiri Olsa 	return add_event(list, idx, &attr,
7126b5fc39bSJiri Olsa 			 pmu_event_name(&attr, head_config));
7135f537a26SJiri Olsa }
7145f537a26SJiri Olsa 
7155d7be90eSJiri Olsa void parse_events_update_lists(struct list_head *list_event,
7165d7be90eSJiri Olsa 			       struct list_head *list_all)
7175d7be90eSJiri Olsa {
7185d7be90eSJiri Olsa 	/*
7195d7be90eSJiri Olsa 	 * Called for single event definition. Update the
7205d7be90eSJiri Olsa 	 * 'all event' list, and reinit the 'signle event'
7215d7be90eSJiri Olsa 	 * list, for next event definition.
7225d7be90eSJiri Olsa 	 */
7235d7be90eSJiri Olsa 	list_splice_tail(list_event, list_all);
724b847cbdcSJiri Olsa 	free(list_event);
7255d7be90eSJiri Olsa }
7265d7be90eSJiri Olsa 
72789812fc8SJiri Olsa int parse_events_modifier(struct list_head *list, char *str)
72861c45981SPaul Mackerras {
72989812fc8SJiri Olsa 	struct perf_evsel *evsel;
73099320cc8SJoerg Roedel 	int exclude = 0, exclude_GH = 0;
73199320cc8SJoerg Roedel 	int eu = 0, ek = 0, eh = 0, eH = 0, eG = 0, precise = 0;
73261c45981SPaul Mackerras 
73389812fc8SJiri Olsa 	if (str == NULL)
73461c45981SPaul Mackerras 		return 0;
735ceb53fbfSIngo Molnar 
73661c45981SPaul Mackerras 	while (*str) {
737ab608344SPeter Zijlstra 		if (*str == 'u') {
738ab608344SPeter Zijlstra 			if (!exclude)
739ab608344SPeter Zijlstra 				exclude = eu = ek = eh = 1;
74061c45981SPaul Mackerras 			eu = 0;
741ab608344SPeter Zijlstra 		} else if (*str == 'k') {
742ab608344SPeter Zijlstra 			if (!exclude)
743ab608344SPeter Zijlstra 				exclude = eu = ek = eh = 1;
74461c45981SPaul Mackerras 			ek = 0;
745ab608344SPeter Zijlstra 		} else if (*str == 'h') {
746ab608344SPeter Zijlstra 			if (!exclude)
747ab608344SPeter Zijlstra 				exclude = eu = ek = eh = 1;
74861c45981SPaul Mackerras 			eh = 0;
74999320cc8SJoerg Roedel 		} else if (*str == 'G') {
75099320cc8SJoerg Roedel 			if (!exclude_GH)
75199320cc8SJoerg Roedel 				exclude_GH = eG = eH = 1;
75299320cc8SJoerg Roedel 			eG = 0;
75399320cc8SJoerg Roedel 		} else if (*str == 'H') {
75499320cc8SJoerg Roedel 			if (!exclude_GH)
75599320cc8SJoerg Roedel 				exclude_GH = eG = eH = 1;
75699320cc8SJoerg Roedel 			eH = 0;
757ab608344SPeter Zijlstra 		} else if (*str == 'p') {
758ab608344SPeter Zijlstra 			precise++;
759ab608344SPeter Zijlstra 		} else
76061c45981SPaul Mackerras 			break;
761ab608344SPeter Zijlstra 
76261c45981SPaul Mackerras 		++str;
76361c45981SPaul Mackerras 	}
76474d5b588SJaswinder Singh Rajput 
76586470930SIngo Molnar 	/*
76689812fc8SJiri Olsa 	 * precise ip:
76789812fc8SJiri Olsa 	 *
76889812fc8SJiri Olsa 	 *  0 - SAMPLE_IP can have arbitrary skid
76989812fc8SJiri Olsa 	 *  1 - SAMPLE_IP must have constant skid
77089812fc8SJiri Olsa 	 *  2 - SAMPLE_IP requested to have 0 skid
77189812fc8SJiri Olsa 	 *  3 - SAMPLE_IP must have 0 skid
77289812fc8SJiri Olsa 	 *
77389812fc8SJiri Olsa 	 *  See also PERF_RECORD_MISC_EXACT_IP
77486470930SIngo Molnar 	 */
77589812fc8SJiri Olsa 	if (precise > 3)
77689812fc8SJiri Olsa 		return -EINVAL;
77786470930SIngo Molnar 
77889812fc8SJiri Olsa 	list_for_each_entry(evsel, list, node) {
77989812fc8SJiri Olsa 		evsel->attr.exclude_user   = eu;
78089812fc8SJiri Olsa 		evsel->attr.exclude_kernel = ek;
78189812fc8SJiri Olsa 		evsel->attr.exclude_hv     = eh;
78289812fc8SJiri Olsa 		evsel->attr.precise_ip     = precise;
78389812fc8SJiri Olsa 		evsel->attr.exclude_host   = eH;
78489812fc8SJiri Olsa 		evsel->attr.exclude_guest  = eG;
785ceb53fbfSIngo Molnar 	}
78686470930SIngo Molnar 
78789812fc8SJiri Olsa 	return 0;
78886470930SIngo Molnar }
78986470930SIngo Molnar 
790f120f9d5SJiri Olsa int parse_events(struct perf_evlist *evlist, const char *str, int unset __used)
79186470930SIngo Molnar {
79289812fc8SJiri Olsa 	LIST_HEAD(list);
7935d7be90eSJiri Olsa 	LIST_HEAD(list_tmp);
79489812fc8SJiri Olsa 	YY_BUFFER_STATE buffer;
79589812fc8SJiri Olsa 	int ret, idx = evlist->nr_entries;
79686470930SIngo Molnar 
79789812fc8SJiri Olsa 	buffer = parse_events__scan_string(str);
79861c45981SPaul Mackerras 
79982ba1f2fSJiri Olsa #ifdef PARSER_DEBUG
80082ba1f2fSJiri Olsa 	parse_events_debug = 1;
80182ba1f2fSJiri Olsa #endif
802b847cbdcSJiri Olsa 	ret = parse_events_parse(&list, &idx);
80386470930SIngo Molnar 
80489812fc8SJiri Olsa 	parse_events__flush_buffer(buffer);
80589812fc8SJiri Olsa 	parse_events__delete_buffer(buffer);
80608d2f762SJiri Olsa 	parse_events_lex_destroy();
807f0c55bcfSStephane Eranian 
80889812fc8SJiri Olsa 	if (!ret) {
80989812fc8SJiri Olsa 		int entries = idx - evlist->nr_entries;
81089812fc8SJiri Olsa 		perf_evlist__splice_list_tail(evlist, &list, entries);
81186470930SIngo Molnar 		return 0;
81286470930SIngo Molnar 	}
81386470930SIngo Molnar 
8145d7be90eSJiri Olsa 	/*
8155d7be90eSJiri Olsa 	 * There are 2 users - builtin-record and builtin-test objects.
8165d7be90eSJiri Olsa 	 * Both call perf_evlist__delete in case of error, so we dont
8175d7be90eSJiri Olsa 	 * need to bother.
8185d7be90eSJiri Olsa 	 */
81989812fc8SJiri Olsa 	fprintf(stderr, "invalid or unsupported event: '%s'\n", str);
82089812fc8SJiri Olsa 	fprintf(stderr, "Run 'perf list' for a list of valid events\n");
82189812fc8SJiri Olsa 	return ret;
82289812fc8SJiri Olsa }
82389812fc8SJiri Olsa 
824f120f9d5SJiri Olsa int parse_events_option(const struct option *opt, const char *str,
825f120f9d5SJiri Olsa 			int unset __used)
826f120f9d5SJiri Olsa {
827f120f9d5SJiri Olsa 	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
828f120f9d5SJiri Olsa 	return parse_events(evlist, str, unset);
829f120f9d5SJiri Olsa }
830f120f9d5SJiri Olsa 
831361c99a6SArnaldo Carvalho de Melo int parse_filter(const struct option *opt, const char *str,
832c171b552SLi Zefan 		 int unset __used)
833c171b552SLi Zefan {
834361c99a6SArnaldo Carvalho de Melo 	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
83569aad6f1SArnaldo Carvalho de Melo 	struct perf_evsel *last = NULL;
836c171b552SLi Zefan 
837361c99a6SArnaldo Carvalho de Melo 	if (evlist->nr_entries > 0)
838361c99a6SArnaldo Carvalho de Melo 		last = list_entry(evlist->entries.prev, struct perf_evsel, node);
83969aad6f1SArnaldo Carvalho de Melo 
84069aad6f1SArnaldo Carvalho de Melo 	if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
841c171b552SLi Zefan 		fprintf(stderr,
842c171b552SLi Zefan 			"-F option should follow a -e tracepoint option\n");
843c171b552SLi Zefan 		return -1;
844c171b552SLi Zefan 	}
845c171b552SLi Zefan 
84669aad6f1SArnaldo Carvalho de Melo 	last->filter = strdup(str);
84769aad6f1SArnaldo Carvalho de Melo 	if (last->filter == NULL) {
848c171b552SLi Zefan 		fprintf(stderr, "not enough memory to hold filter string\n");
849c171b552SLi Zefan 		return -1;
850c171b552SLi Zefan 	}
851c171b552SLi Zefan 
852c171b552SLi Zefan 	return 0;
853c171b552SLi Zefan }
854c171b552SLi Zefan 
85586470930SIngo Molnar static const char * const event_type_descriptors[] = {
85686470930SIngo Molnar 	"Hardware event",
85786470930SIngo Molnar 	"Software event",
85886470930SIngo Molnar 	"Tracepoint event",
85986470930SIngo Molnar 	"Hardware cache event",
86041bdcb23SLiming Wang 	"Raw hardware event descriptor",
86141bdcb23SLiming Wang 	"Hardware breakpoint",
86286470930SIngo Molnar };
86386470930SIngo Molnar 
86486470930SIngo Molnar /*
865f6bdafefSJason Baron  * Print the events from <debugfs_mount_point>/tracing/events
866f6bdafefSJason Baron  */
867f6bdafefSJason Baron 
868668b8788SArnaldo Carvalho de Melo void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
869f6bdafefSJason Baron {
870f6bdafefSJason Baron 	DIR *sys_dir, *evt_dir;
871f6bdafefSJason Baron 	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
872f6bdafefSJason Baron 	char evt_path[MAXPATHLEN];
873725b1368SEric Dumazet 	char dir_path[MAXPATHLEN];
874f6bdafefSJason Baron 
875ebf294bfSArnaldo Carvalho de Melo 	if (debugfs_valid_mountpoint(tracing_events_path))
876f6bdafefSJason Baron 		return;
877f6bdafefSJason Baron 
878ebf294bfSArnaldo Carvalho de Melo 	sys_dir = opendir(tracing_events_path);
879f6bdafefSJason Baron 	if (!sys_dir)
880725b1368SEric Dumazet 		return;
881f6bdafefSJason Baron 
8826b58e7f1SUlrich Drepper 	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
883668b8788SArnaldo Carvalho de Melo 		if (subsys_glob != NULL &&
884668b8788SArnaldo Carvalho de Melo 		    !strglobmatch(sys_dirent.d_name, subsys_glob))
885668b8788SArnaldo Carvalho de Melo 			continue;
886725b1368SEric Dumazet 
887ebf294bfSArnaldo Carvalho de Melo 		snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
888725b1368SEric Dumazet 			 sys_dirent.d_name);
889725b1368SEric Dumazet 		evt_dir = opendir(dir_path);
890725b1368SEric Dumazet 		if (!evt_dir)
8916b58e7f1SUlrich Drepper 			continue;
892725b1368SEric Dumazet 
8936b58e7f1SUlrich Drepper 		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
894668b8788SArnaldo Carvalho de Melo 			if (event_glob != NULL &&
895668b8788SArnaldo Carvalho de Melo 			    !strglobmatch(evt_dirent.d_name, event_glob))
896668b8788SArnaldo Carvalho de Melo 				continue;
897668b8788SArnaldo Carvalho de Melo 
898f6bdafefSJason Baron 			snprintf(evt_path, MAXPATHLEN, "%s:%s",
899f6bdafefSJason Baron 				 sys_dirent.d_name, evt_dirent.d_name);
900947b4ad1SIngo Molnar 			printf("  %-50s [%s]\n", evt_path,
90141bdcb23SLiming Wang 				event_type_descriptors[PERF_TYPE_TRACEPOINT]);
902f6bdafefSJason Baron 		}
903f6bdafefSJason Baron 		closedir(evt_dir);
904f6bdafefSJason Baron 	}
905f6bdafefSJason Baron 	closedir(sys_dir);
906f6bdafefSJason Baron }
907f6bdafefSJason Baron 
908f6bdafefSJason Baron /*
90920c457b8SThomas Renninger  * Check whether event is in <debugfs_mount_point>/tracing/events
91020c457b8SThomas Renninger  */
91120c457b8SThomas Renninger 
91220c457b8SThomas Renninger int is_valid_tracepoint(const char *event_string)
91320c457b8SThomas Renninger {
91420c457b8SThomas Renninger 	DIR *sys_dir, *evt_dir;
91520c457b8SThomas Renninger 	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
91620c457b8SThomas Renninger 	char evt_path[MAXPATHLEN];
91720c457b8SThomas Renninger 	char dir_path[MAXPATHLEN];
91820c457b8SThomas Renninger 
919ebf294bfSArnaldo Carvalho de Melo 	if (debugfs_valid_mountpoint(tracing_events_path))
92020c457b8SThomas Renninger 		return 0;
92120c457b8SThomas Renninger 
922ebf294bfSArnaldo Carvalho de Melo 	sys_dir = opendir(tracing_events_path);
92320c457b8SThomas Renninger 	if (!sys_dir)
92420c457b8SThomas Renninger 		return 0;
92520c457b8SThomas Renninger 
92620c457b8SThomas Renninger 	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
92720c457b8SThomas Renninger 
928ebf294bfSArnaldo Carvalho de Melo 		snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
92920c457b8SThomas Renninger 			 sys_dirent.d_name);
93020c457b8SThomas Renninger 		evt_dir = opendir(dir_path);
93120c457b8SThomas Renninger 		if (!evt_dir)
93220c457b8SThomas Renninger 			continue;
93320c457b8SThomas Renninger 
93420c457b8SThomas Renninger 		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
93520c457b8SThomas Renninger 			snprintf(evt_path, MAXPATHLEN, "%s:%s",
93620c457b8SThomas Renninger 				 sys_dirent.d_name, evt_dirent.d_name);
93720c457b8SThomas Renninger 			if (!strcmp(evt_path, event_string)) {
93820c457b8SThomas Renninger 				closedir(evt_dir);
93920c457b8SThomas Renninger 				closedir(sys_dir);
94020c457b8SThomas Renninger 				return 1;
94120c457b8SThomas Renninger 			}
94220c457b8SThomas Renninger 		}
94320c457b8SThomas Renninger 		closedir(evt_dir);
94420c457b8SThomas Renninger 	}
94520c457b8SThomas Renninger 	closedir(sys_dir);
94620c457b8SThomas Renninger 	return 0;
94720c457b8SThomas Renninger }
94820c457b8SThomas Renninger 
949668b8788SArnaldo Carvalho de Melo void print_events_type(u8 type)
950668b8788SArnaldo Carvalho de Melo {
951668b8788SArnaldo Carvalho de Melo 	struct event_symbol *syms = event_symbols;
952668b8788SArnaldo Carvalho de Melo 	unsigned int i;
953668b8788SArnaldo Carvalho de Melo 	char name[64];
954668b8788SArnaldo Carvalho de Melo 
955668b8788SArnaldo Carvalho de Melo 	for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
956668b8788SArnaldo Carvalho de Melo 		if (type != syms->type)
957668b8788SArnaldo Carvalho de Melo 			continue;
958668b8788SArnaldo Carvalho de Melo 
959668b8788SArnaldo Carvalho de Melo 		if (strlen(syms->alias))
960668b8788SArnaldo Carvalho de Melo 			snprintf(name, sizeof(name),  "%s OR %s",
961668b8788SArnaldo Carvalho de Melo 				 syms->symbol, syms->alias);
962668b8788SArnaldo Carvalho de Melo 		else
963668b8788SArnaldo Carvalho de Melo 			snprintf(name, sizeof(name), "%s", syms->symbol);
964668b8788SArnaldo Carvalho de Melo 
965947b4ad1SIngo Molnar 		printf("  %-50s [%s]\n", name,
966668b8788SArnaldo Carvalho de Melo 			event_type_descriptors[type]);
967668b8788SArnaldo Carvalho de Melo 	}
968668b8788SArnaldo Carvalho de Melo }
969668b8788SArnaldo Carvalho de Melo 
970668b8788SArnaldo Carvalho de Melo int print_hwcache_events(const char *event_glob)
971668b8788SArnaldo Carvalho de Melo {
972668b8788SArnaldo Carvalho de Melo 	unsigned int type, op, i, printed = 0;
973668b8788SArnaldo Carvalho de Melo 
974668b8788SArnaldo Carvalho de Melo 	for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
975668b8788SArnaldo Carvalho de Melo 		for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
976668b8788SArnaldo Carvalho de Melo 			/* skip invalid cache type */
977668b8788SArnaldo Carvalho de Melo 			if (!is_cache_op_valid(type, op))
978668b8788SArnaldo Carvalho de Melo 				continue;
979668b8788SArnaldo Carvalho de Melo 
980668b8788SArnaldo Carvalho de Melo 			for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
981668b8788SArnaldo Carvalho de Melo 				char *name = event_cache_name(type, op, i);
982668b8788SArnaldo Carvalho de Melo 
983947b4ad1SIngo Molnar 				if (event_glob != NULL && !strglobmatch(name, event_glob))
984668b8788SArnaldo Carvalho de Melo 					continue;
985668b8788SArnaldo Carvalho de Melo 
986947b4ad1SIngo Molnar 				printf("  %-50s [%s]\n", name,
987668b8788SArnaldo Carvalho de Melo 					event_type_descriptors[PERF_TYPE_HW_CACHE]);
988668b8788SArnaldo Carvalho de Melo 				++printed;
989668b8788SArnaldo Carvalho de Melo 			}
990668b8788SArnaldo Carvalho de Melo 		}
991668b8788SArnaldo Carvalho de Melo 	}
992668b8788SArnaldo Carvalho de Melo 
993668b8788SArnaldo Carvalho de Melo 	return printed;
994668b8788SArnaldo Carvalho de Melo }
995668b8788SArnaldo Carvalho de Melo 
99620c457b8SThomas Renninger /*
99786470930SIngo Molnar  * Print the help text for the event symbols:
99886470930SIngo Molnar  */
999668b8788SArnaldo Carvalho de Melo void print_events(const char *event_glob)
100086470930SIngo Molnar {
1001668b8788SArnaldo Carvalho de Melo 	unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0;
1002947b4ad1SIngo Molnar 	struct event_symbol *syms = event_symbols;
1003947b4ad1SIngo Molnar 	char name[MAX_NAME_LEN];
100486470930SIngo Molnar 
1005689d3018SMarti Raudsepp 	printf("\n");
1006689d3018SMarti Raudsepp 	printf("List of pre-defined events (to be used in -e):\n");
100786470930SIngo Molnar 
100886470930SIngo Molnar 	for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
100941bdcb23SLiming Wang 		type = syms->type;
101086470930SIngo Molnar 
1011668b8788SArnaldo Carvalho de Melo 		if (type != prev_type && printed) {
1012689d3018SMarti Raudsepp 			printf("\n");
1013668b8788SArnaldo Carvalho de Melo 			printed = 0;
1014668b8788SArnaldo Carvalho de Melo 			ntypes_printed++;
1015668b8788SArnaldo Carvalho de Melo 		}
1016668b8788SArnaldo Carvalho de Melo 
1017668b8788SArnaldo Carvalho de Melo 		if (event_glob != NULL &&
1018668b8788SArnaldo Carvalho de Melo 		    !(strglobmatch(syms->symbol, event_glob) ||
1019668b8788SArnaldo Carvalho de Melo 		      (syms->alias && strglobmatch(syms->alias, event_glob))))
1020668b8788SArnaldo Carvalho de Melo 			continue;
102186470930SIngo Molnar 
102274d5b588SJaswinder Singh Rajput 		if (strlen(syms->alias))
1023947b4ad1SIngo Molnar 			snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
102474d5b588SJaswinder Singh Rajput 		else
1025947b4ad1SIngo Molnar 			strncpy(name, syms->symbol, MAX_NAME_LEN);
1026947b4ad1SIngo Molnar 		printf("  %-50s [%s]\n", name,
102786470930SIngo Molnar 			event_type_descriptors[type]);
102886470930SIngo Molnar 
102986470930SIngo Molnar 		prev_type = type;
1030668b8788SArnaldo Carvalho de Melo 		++printed;
103186470930SIngo Molnar 	}
103286470930SIngo Molnar 
1033668b8788SArnaldo Carvalho de Melo 	if (ntypes_printed) {
1034668b8788SArnaldo Carvalho de Melo 		printed = 0;
1035689d3018SMarti Raudsepp 		printf("\n");
1036668b8788SArnaldo Carvalho de Melo 	}
1037668b8788SArnaldo Carvalho de Melo 	print_hwcache_events(event_glob);
103873c24cb8SJaswinder Singh Rajput 
1039668b8788SArnaldo Carvalho de Melo 	if (event_glob != NULL)
1040668b8788SArnaldo Carvalho de Melo 		return;
104173c24cb8SJaswinder Singh Rajput 
1042689d3018SMarti Raudsepp 	printf("\n");
1043947b4ad1SIngo Molnar 	printf("  %-50s [%s]\n",
10445f537a26SJiri Olsa 	       "rNNN",
10451cf4a063SArnaldo Carvalho de Melo 	       event_type_descriptors[PERF_TYPE_RAW]);
10465f537a26SJiri Olsa 	printf("  %-50s [%s]\n",
10475f537a26SJiri Olsa 	       "cpu/t1=v1[,t2=v2,t3 ...]/modifier",
10485f537a26SJiri Olsa 	       event_type_descriptors[PERF_TYPE_RAW]);
10495f537a26SJiri Olsa 	printf("   (see 'perf list --help' on how to encode it)\n");
1050689d3018SMarti Raudsepp 	printf("\n");
105186470930SIngo Molnar 
1052947b4ad1SIngo Molnar 	printf("  %-50s [%s]\n",
105341bdcb23SLiming Wang 			"mem:<addr>[:access]",
105441bdcb23SLiming Wang 			event_type_descriptors[PERF_TYPE_BREAKPOINT]);
10551b290d67SFrederic Weisbecker 	printf("\n");
10561b290d67SFrederic Weisbecker 
1057668b8788SArnaldo Carvalho de Melo 	print_tracepoint_events(NULL, NULL);
105886470930SIngo Molnar }
10598f707d84SJiri Olsa 
10608f707d84SJiri Olsa int parse_events__is_hardcoded_term(struct parse_events__term *term)
10618f707d84SJiri Olsa {
106216fa7e82SJiri Olsa 	return term->type_term != PARSE_EVENTS__TERM_TYPE_USER;
10638f707d84SJiri Olsa }
10648f707d84SJiri Olsa 
106516fa7e82SJiri Olsa static int new_term(struct parse_events__term **_term, int type_val,
106616fa7e82SJiri Olsa 		    int type_term, char *config,
106716fa7e82SJiri Olsa 		    char *str, long num)
10688f707d84SJiri Olsa {
10698f707d84SJiri Olsa 	struct parse_events__term *term;
10708f707d84SJiri Olsa 
10718f707d84SJiri Olsa 	term = zalloc(sizeof(*term));
10728f707d84SJiri Olsa 	if (!term)
10738f707d84SJiri Olsa 		return -ENOMEM;
10748f707d84SJiri Olsa 
10758f707d84SJiri Olsa 	INIT_LIST_HEAD(&term->list);
107616fa7e82SJiri Olsa 	term->type_val  = type_val;
107716fa7e82SJiri Olsa 	term->type_term = type_term;
10788f707d84SJiri Olsa 	term->config = config;
10798f707d84SJiri Olsa 
108016fa7e82SJiri Olsa 	switch (type_val) {
10818f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_NUM:
10828f707d84SJiri Olsa 		term->val.num = num;
10838f707d84SJiri Olsa 		break;
10848f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_STR:
10858f707d84SJiri Olsa 		term->val.str = str;
10868f707d84SJiri Olsa 		break;
10878f707d84SJiri Olsa 	default:
10888f707d84SJiri Olsa 		return -EINVAL;
10898f707d84SJiri Olsa 	}
10908f707d84SJiri Olsa 
10918f707d84SJiri Olsa 	*_term = term;
10928f707d84SJiri Olsa 	return 0;
10938f707d84SJiri Olsa }
10948f707d84SJiri Olsa 
109516fa7e82SJiri Olsa int parse_events__term_num(struct parse_events__term **term,
109616fa7e82SJiri Olsa 			   int type_term, char *config, long num)
109716fa7e82SJiri Olsa {
109816fa7e82SJiri Olsa 	return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term,
109916fa7e82SJiri Olsa 			config, NULL, num);
110016fa7e82SJiri Olsa }
110116fa7e82SJiri Olsa 
110216fa7e82SJiri Olsa int parse_events__term_str(struct parse_events__term **term,
110316fa7e82SJiri Olsa 			   int type_term, char *config, char *str)
110416fa7e82SJiri Olsa {
110516fa7e82SJiri Olsa 	return new_term(term, PARSE_EVENTS__TERM_TYPE_STR, type_term,
110616fa7e82SJiri Olsa 			config, str, 0);
110716fa7e82SJiri Olsa }
110816fa7e82SJiri Olsa 
11098f707d84SJiri Olsa void parse_events__free_terms(struct list_head *terms)
11108f707d84SJiri Olsa {
11118f707d84SJiri Olsa 	struct parse_events__term *term, *h;
11128f707d84SJiri Olsa 
11138f707d84SJiri Olsa 	list_for_each_entry_safe(term, h, terms, list)
11148f707d84SJiri Olsa 		free(term);
11158f707d84SJiri Olsa 
11168f707d84SJiri Olsa 	free(terms);
11178f707d84SJiri Olsa }
1118