xref: /linux/tools/perf/util/parse-events.c (revision 549104f22b3cd4761145eb5fba6ee4d59822da61)
186470930SIngo Molnar 
286470930SIngo Molnar #include "util.h"
36b58e7f1SUlrich Drepper #include "../perf.h"
486470930SIngo Molnar #include "parse-options.h"
586470930SIngo Molnar #include "parse-events.h"
686470930SIngo Molnar #include "exec_cmd.h"
786470930SIngo Molnar #include "string.h"
85beeded1SJason Baron #include "cache.h"
98755a8f2SArjan van de Ven #include "header.h"
10*549104f2SClark Williams #include "debugfs.h"
1186470930SIngo Molnar 
1286470930SIngo Molnar int				nr_counters;
1386470930SIngo Molnar 
14cdd6c482SIngo Molnar struct perf_event_attr		attrs[MAX_COUNTERS];
15c171b552SLi Zefan char				*filters[MAX_COUNTERS];
1686470930SIngo Molnar 
1786470930SIngo Molnar struct event_symbol {
189cffa8d5SPaul Mackerras 	u8		type;
199cffa8d5SPaul Mackerras 	u64		config;
2083a0944fSIngo Molnar 	const char	*symbol;
2183a0944fSIngo Molnar 	const char	*alias;
2286470930SIngo Molnar };
2386470930SIngo Molnar 
24bcd3279fSFrederic Weisbecker enum event_result {
25bcd3279fSFrederic Weisbecker 	EVT_FAILED,
26bcd3279fSFrederic Weisbecker 	EVT_HANDLED,
27bcd3279fSFrederic Weisbecker 	EVT_HANDLED_ALL
28bcd3279fSFrederic Weisbecker };
29bcd3279fSFrederic Weisbecker 
305beeded1SJason Baron char debugfs_path[MAXPATHLEN];
315beeded1SJason Baron 
3251e26842SJaswinder Singh Rajput #define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
3351e26842SJaswinder Singh Rajput #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
3486470930SIngo Molnar 
3586470930SIngo Molnar static struct event_symbol event_symbols[] = {
3674d5b588SJaswinder Singh Rajput   { CHW(CPU_CYCLES),		"cpu-cycles",		"cycles"	},
3774d5b588SJaswinder Singh Rajput   { CHW(INSTRUCTIONS),		"instructions",		""		},
3874d5b588SJaswinder Singh Rajput   { CHW(CACHE_REFERENCES),	"cache-references",	""		},
3974d5b588SJaswinder Singh Rajput   { CHW(CACHE_MISSES),		"cache-misses",		""		},
4074d5b588SJaswinder Singh Rajput   { CHW(BRANCH_INSTRUCTIONS),	"branch-instructions",	"branches"	},
4174d5b588SJaswinder Singh Rajput   { CHW(BRANCH_MISSES),		"branch-misses",	""		},
4274d5b588SJaswinder Singh Rajput   { CHW(BUS_CYCLES),		"bus-cycles",		""		},
4386470930SIngo Molnar 
4474d5b588SJaswinder Singh Rajput   { CSW(CPU_CLOCK),		"cpu-clock",		""		},
4574d5b588SJaswinder Singh Rajput   { CSW(TASK_CLOCK),		"task-clock",		""		},
46c0c22dbfSJaswinder Singh Rajput   { CSW(PAGE_FAULTS),		"page-faults",		"faults"	},
4774d5b588SJaswinder Singh Rajput   { CSW(PAGE_FAULTS_MIN),	"minor-faults",		""		},
4874d5b588SJaswinder Singh Rajput   { CSW(PAGE_FAULTS_MAJ),	"major-faults",		""		},
4974d5b588SJaswinder Singh Rajput   { CSW(CONTEXT_SWITCHES),	"context-switches",	"cs"		},
5074d5b588SJaswinder Singh Rajput   { CSW(CPU_MIGRATIONS),	"cpu-migrations",	"migrations"	},
5186470930SIngo Molnar };
5286470930SIngo Molnar 
53cdd6c482SIngo Molnar #define __PERF_EVENT_FIELD(config, name) \
54cdd6c482SIngo Molnar 	((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT)
5586470930SIngo Molnar 
56cdd6c482SIngo Molnar #define PERF_EVENT_RAW(config)	__PERF_EVENT_FIELD(config, RAW)
57cdd6c482SIngo Molnar #define PERF_EVENT_CONFIG(config)	__PERF_EVENT_FIELD(config, CONFIG)
58cdd6c482SIngo Molnar #define PERF_EVENT_TYPE(config)	__PERF_EVENT_FIELD(config, TYPE)
59cdd6c482SIngo Molnar #define PERF_EVENT_ID(config)		__PERF_EVENT_FIELD(config, EVENT)
6086470930SIngo Molnar 
6183a0944fSIngo Molnar static const char *hw_event_names[] = {
6286470930SIngo Molnar 	"cycles",
6386470930SIngo Molnar 	"instructions",
6486470930SIngo Molnar 	"cache-references",
6586470930SIngo Molnar 	"cache-misses",
6686470930SIngo Molnar 	"branches",
6786470930SIngo Molnar 	"branch-misses",
6886470930SIngo Molnar 	"bus-cycles",
6986470930SIngo Molnar };
7086470930SIngo Molnar 
7183a0944fSIngo Molnar static const char *sw_event_names[] = {
7244175b6fSIngo Molnar 	"cpu-clock-msecs",
7344175b6fSIngo Molnar 	"task-clock-msecs",
7486470930SIngo Molnar 	"page-faults",
7586470930SIngo Molnar 	"context-switches",
7686470930SIngo Molnar 	"CPU-migrations",
7786470930SIngo Molnar 	"minor-faults",
7886470930SIngo Molnar 	"major-faults",
7986470930SIngo Molnar };
8086470930SIngo Molnar 
8186470930SIngo Molnar #define MAX_ALIASES 8
8286470930SIngo Molnar 
8383a0944fSIngo Molnar static const char *hw_cache[][MAX_ALIASES] = {
849590b7baSAnton Blanchard  { "L1-dcache",	"l1-d",		"l1d",		"L1-data",		},
859590b7baSAnton Blanchard  { "L1-icache",	"l1-i",		"l1i",		"L1-instruction",	},
86e5c59547SJaswinder Singh Rajput  { "LLC",	"L2"							},
87e5c59547SJaswinder Singh Rajput  { "dTLB",	"d-tlb",	"Data-TLB",				},
88e5c59547SJaswinder Singh Rajput  { "iTLB",	"i-tlb",	"Instruction-TLB",			},
89e5c59547SJaswinder Singh Rajput  { "branch",	"branches",	"bpu",		"btb",		"bpc",	},
9086470930SIngo Molnar };
9186470930SIngo Molnar 
9283a0944fSIngo Molnar static const char *hw_cache_op[][MAX_ALIASES] = {
93e5c59547SJaswinder Singh Rajput  { "load",	"loads",	"read",					},
94e5c59547SJaswinder Singh Rajput  { "store",	"stores",	"write",				},
95e5c59547SJaswinder Singh Rajput  { "prefetch",	"prefetches",	"speculative-read", "speculative-load",	},
9686470930SIngo Molnar };
9786470930SIngo Molnar 
9883a0944fSIngo Molnar static const char *hw_cache_result[][MAX_ALIASES] = {
99e5c59547SJaswinder Singh Rajput  { "refs",	"Reference",	"ops",		"access",		},
100e5c59547SJaswinder Singh Rajput  { "misses",	"miss",							},
10186470930SIngo Molnar };
10286470930SIngo Molnar 
10306813f6cSJaswinder Singh Rajput #define C(x)		PERF_COUNT_HW_CACHE_##x
10406813f6cSJaswinder Singh Rajput #define CACHE_READ	(1 << C(OP_READ))
10506813f6cSJaswinder Singh Rajput #define CACHE_WRITE	(1 << C(OP_WRITE))
10606813f6cSJaswinder Singh Rajput #define CACHE_PREFETCH	(1 << C(OP_PREFETCH))
10706813f6cSJaswinder Singh Rajput #define COP(x)		(1 << x)
10806813f6cSJaswinder Singh Rajput 
10906813f6cSJaswinder Singh Rajput /*
11006813f6cSJaswinder Singh Rajput  * cache operartion stat
11106813f6cSJaswinder Singh Rajput  * L1I : Read and prefetch only
11206813f6cSJaswinder Singh Rajput  * ITLB and BPU : Read-only
11306813f6cSJaswinder Singh Rajput  */
11406813f6cSJaswinder Singh Rajput static unsigned long hw_cache_stat[C(MAX)] = {
11506813f6cSJaswinder Singh Rajput  [C(L1D)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
11606813f6cSJaswinder Singh Rajput  [C(L1I)]	= (CACHE_READ | CACHE_PREFETCH),
11706813f6cSJaswinder Singh Rajput  [C(LL)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
11806813f6cSJaswinder Singh Rajput  [C(DTLB)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
11906813f6cSJaswinder Singh Rajput  [C(ITLB)]	= (CACHE_READ),
12006813f6cSJaswinder Singh Rajput  [C(BPU)]	= (CACHE_READ),
12106813f6cSJaswinder Singh Rajput };
12206813f6cSJaswinder Singh Rajput 
1236b58e7f1SUlrich Drepper #define for_each_subsystem(sys_dir, sys_dirent, sys_next)	       \
124f6bdafefSJason Baron 	while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next)	       \
1256b58e7f1SUlrich Drepper 	if (sys_dirent.d_type == DT_DIR &&				       \
126f6bdafefSJason Baron 	   (strcmp(sys_dirent.d_name, ".")) &&				       \
127f6bdafefSJason Baron 	   (strcmp(sys_dirent.d_name, "..")))
128f6bdafefSJason Baron 
129ae07b63fSPeter Zijlstra static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
130ae07b63fSPeter Zijlstra {
131ae07b63fSPeter Zijlstra 	char evt_path[MAXPATHLEN];
132ae07b63fSPeter Zijlstra 	int fd;
133ae07b63fSPeter Zijlstra 
134ae07b63fSPeter Zijlstra 	snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
135ae07b63fSPeter Zijlstra 			sys_dir->d_name, evt_dir->d_name);
136ae07b63fSPeter Zijlstra 	fd = open(evt_path, O_RDONLY);
137ae07b63fSPeter Zijlstra 	if (fd < 0)
138ae07b63fSPeter Zijlstra 		return -EINVAL;
139ae07b63fSPeter Zijlstra 	close(fd);
140ae07b63fSPeter Zijlstra 
141ae07b63fSPeter Zijlstra 	return 0;
142ae07b63fSPeter Zijlstra }
143ae07b63fSPeter Zijlstra 
1446b58e7f1SUlrich Drepper #define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next)	       \
145f6bdafefSJason Baron 	while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next)        \
1466b58e7f1SUlrich Drepper 	if (evt_dirent.d_type == DT_DIR &&				       \
147f6bdafefSJason Baron 	   (strcmp(evt_dirent.d_name, ".")) &&				       \
148ae07b63fSPeter Zijlstra 	   (strcmp(evt_dirent.d_name, "..")) &&				       \
149ae07b63fSPeter Zijlstra 	   (!tp_event_has_id(&sys_dirent, &evt_dirent)))
150f6bdafefSJason Baron 
151270bbbe8SLi Zefan #define MAX_EVENT_LENGTH 512
152f6bdafefSJason Baron 
153f6bdafefSJason Baron 
1541ef2ed10SFrederic Weisbecker struct tracepoint_path *tracepoint_id_to_path(u64 config)
155f6bdafefSJason Baron {
1561ef2ed10SFrederic Weisbecker 	struct tracepoint_path *path = NULL;
157f6bdafefSJason Baron 	DIR *sys_dir, *evt_dir;
158f6bdafefSJason Baron 	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
159f6bdafefSJason Baron 	char id_buf[4];
160725b1368SEric Dumazet 	int fd;
161f6bdafefSJason Baron 	u64 id;
162f6bdafefSJason Baron 	char evt_path[MAXPATHLEN];
163725b1368SEric Dumazet 	char dir_path[MAXPATHLEN];
164f6bdafefSJason Baron 
165*549104f2SClark Williams 	if (debugfs_valid_mountpoint(debugfs_path))
1661ef2ed10SFrederic Weisbecker 		return NULL;
167f6bdafefSJason Baron 
1685beeded1SJason Baron 	sys_dir = opendir(debugfs_path);
169f6bdafefSJason Baron 	if (!sys_dir)
170725b1368SEric Dumazet 		return NULL;
171f6bdafefSJason Baron 
1726b58e7f1SUlrich Drepper 	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
173725b1368SEric Dumazet 
174725b1368SEric Dumazet 		snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
175725b1368SEric Dumazet 			 sys_dirent.d_name);
176725b1368SEric Dumazet 		evt_dir = opendir(dir_path);
177725b1368SEric Dumazet 		if (!evt_dir)
1786b58e7f1SUlrich Drepper 			continue;
179725b1368SEric Dumazet 
1806b58e7f1SUlrich Drepper 		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
181725b1368SEric Dumazet 
182725b1368SEric Dumazet 			snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
183f6bdafefSJason Baron 				 evt_dirent.d_name);
184725b1368SEric Dumazet 			fd = open(evt_path, O_RDONLY);
185f6bdafefSJason Baron 			if (fd < 0)
186f6bdafefSJason Baron 				continue;
187f6bdafefSJason Baron 			if (read(fd, id_buf, sizeof(id_buf)) < 0) {
188f6bdafefSJason Baron 				close(fd);
189f6bdafefSJason Baron 				continue;
190f6bdafefSJason Baron 			}
191f6bdafefSJason Baron 			close(fd);
192f6bdafefSJason Baron 			id = atoll(id_buf);
193f6bdafefSJason Baron 			if (id == config) {
194f6bdafefSJason Baron 				closedir(evt_dir);
195f6bdafefSJason Baron 				closedir(sys_dir);
1961ef2ed10SFrederic Weisbecker 				path = calloc(1, sizeof(path));
1971ef2ed10SFrederic Weisbecker 				path->system = malloc(MAX_EVENT_LENGTH);
1981ef2ed10SFrederic Weisbecker 				if (!path->system) {
1991ef2ed10SFrederic Weisbecker 					free(path);
2001ef2ed10SFrederic Weisbecker 					return NULL;
2011ef2ed10SFrederic Weisbecker 				}
2021ef2ed10SFrederic Weisbecker 				path->name = malloc(MAX_EVENT_LENGTH);
2031ef2ed10SFrederic Weisbecker 				if (!path->name) {
2041ef2ed10SFrederic Weisbecker 					free(path->system);
2051ef2ed10SFrederic Weisbecker 					free(path);
2061ef2ed10SFrederic Weisbecker 					return NULL;
2071ef2ed10SFrederic Weisbecker 				}
2081ef2ed10SFrederic Weisbecker 				strncpy(path->system, sys_dirent.d_name,
2091ef2ed10SFrederic Weisbecker 					MAX_EVENT_LENGTH);
2101ef2ed10SFrederic Weisbecker 				strncpy(path->name, evt_dirent.d_name,
2111ef2ed10SFrederic Weisbecker 					MAX_EVENT_LENGTH);
2121ef2ed10SFrederic Weisbecker 				return path;
213f6bdafefSJason Baron 			}
214f6bdafefSJason Baron 		}
215f6bdafefSJason Baron 		closedir(evt_dir);
216f6bdafefSJason Baron 	}
217f6bdafefSJason Baron 
218f6bdafefSJason Baron 	closedir(sys_dir);
2191ef2ed10SFrederic Weisbecker 	return NULL;
2201ef2ed10SFrederic Weisbecker }
2211ef2ed10SFrederic Weisbecker 
2221ef2ed10SFrederic Weisbecker #define TP_PATH_LEN (MAX_EVENT_LENGTH * 2 + 1)
2231ef2ed10SFrederic Weisbecker static const char *tracepoint_id_to_name(u64 config)
2241ef2ed10SFrederic Weisbecker {
2251ef2ed10SFrederic Weisbecker 	static char buf[TP_PATH_LEN];
2261ef2ed10SFrederic Weisbecker 	struct tracepoint_path *path;
2271ef2ed10SFrederic Weisbecker 
2281ef2ed10SFrederic Weisbecker 	path = tracepoint_id_to_path(config);
2291ef2ed10SFrederic Weisbecker 	if (path) {
2301ef2ed10SFrederic Weisbecker 		snprintf(buf, TP_PATH_LEN, "%s:%s", path->system, path->name);
2311ef2ed10SFrederic Weisbecker 		free(path->name);
2321ef2ed10SFrederic Weisbecker 		free(path->system);
2331ef2ed10SFrederic Weisbecker 		free(path);
2341ef2ed10SFrederic Weisbecker 	} else
2351ef2ed10SFrederic Weisbecker 		snprintf(buf, TP_PATH_LEN, "%s:%s", "unknown", "unknown");
2361ef2ed10SFrederic Weisbecker 
2371ef2ed10SFrederic Weisbecker 	return buf;
238f6bdafefSJason Baron }
239f6bdafefSJason Baron 
24006813f6cSJaswinder Singh Rajput static int is_cache_op_valid(u8 cache_type, u8 cache_op)
24106813f6cSJaswinder Singh Rajput {
24206813f6cSJaswinder Singh Rajput 	if (hw_cache_stat[cache_type] & COP(cache_op))
24306813f6cSJaswinder Singh Rajput 		return 1;	/* valid */
24406813f6cSJaswinder Singh Rajput 	else
24506813f6cSJaswinder Singh Rajput 		return 0;	/* invalid */
24606813f6cSJaswinder Singh Rajput }
24706813f6cSJaswinder Singh Rajput 
248e5c59547SJaswinder Singh Rajput static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
249e5c59547SJaswinder Singh Rajput {
250e5c59547SJaswinder Singh Rajput 	static char name[50];
251e5c59547SJaswinder Singh Rajput 
252e5c59547SJaswinder Singh Rajput 	if (cache_result) {
253e5c59547SJaswinder Singh Rajput 		sprintf(name, "%s-%s-%s", hw_cache[cache_type][0],
254e5c59547SJaswinder Singh Rajput 			hw_cache_op[cache_op][0],
255e5c59547SJaswinder Singh Rajput 			hw_cache_result[cache_result][0]);
256e5c59547SJaswinder Singh Rajput 	} else {
257e5c59547SJaswinder Singh Rajput 		sprintf(name, "%s-%s", hw_cache[cache_type][0],
258e5c59547SJaswinder Singh Rajput 			hw_cache_op[cache_op][1]);
259e5c59547SJaswinder Singh Rajput 	}
260e5c59547SJaswinder Singh Rajput 
261e5c59547SJaswinder Singh Rajput 	return name;
262e5c59547SJaswinder Singh Rajput }
263e5c59547SJaswinder Singh Rajput 
26483a0944fSIngo Molnar const char *event_name(int counter)
26586470930SIngo Molnar {
2669cffa8d5SPaul Mackerras 	u64 config = attrs[counter].config;
26786470930SIngo Molnar 	int type = attrs[counter].type;
2688f18aec5SPeter Zijlstra 
2698f18aec5SPeter Zijlstra 	return __event_name(type, config);
2708f18aec5SPeter Zijlstra }
2718f18aec5SPeter Zijlstra 
27283a0944fSIngo Molnar const char *__event_name(int type, u64 config)
2738f18aec5SPeter Zijlstra {
27486470930SIngo Molnar 	static char buf[32];
27586470930SIngo Molnar 
2768f18aec5SPeter Zijlstra 	if (type == PERF_TYPE_RAW) {
27786470930SIngo Molnar 		sprintf(buf, "raw 0x%llx", config);
27886470930SIngo Molnar 		return buf;
27986470930SIngo Molnar 	}
28086470930SIngo Molnar 
28186470930SIngo Molnar 	switch (type) {
28286470930SIngo Molnar 	case PERF_TYPE_HARDWARE:
283f4dbfa8fSPeter Zijlstra 		if (config < PERF_COUNT_HW_MAX)
28486470930SIngo Molnar 			return hw_event_names[config];
28586470930SIngo Molnar 		return "unknown-hardware";
28686470930SIngo Molnar 
28786470930SIngo Molnar 	case PERF_TYPE_HW_CACHE: {
2889cffa8d5SPaul Mackerras 		u8 cache_type, cache_op, cache_result;
28986470930SIngo Molnar 
29086470930SIngo Molnar 		cache_type   = (config >>  0) & 0xff;
29186470930SIngo Molnar 		if (cache_type > PERF_COUNT_HW_CACHE_MAX)
29286470930SIngo Molnar 			return "unknown-ext-hardware-cache-type";
29386470930SIngo Molnar 
29486470930SIngo Molnar 		cache_op     = (config >>  8) & 0xff;
29586470930SIngo Molnar 		if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX)
29686470930SIngo Molnar 			return "unknown-ext-hardware-cache-op";
29786470930SIngo Molnar 
29886470930SIngo Molnar 		cache_result = (config >> 16) & 0xff;
29986470930SIngo Molnar 		if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX)
30086470930SIngo Molnar 			return "unknown-ext-hardware-cache-result";
30186470930SIngo Molnar 
30206813f6cSJaswinder Singh Rajput 		if (!is_cache_op_valid(cache_type, cache_op))
30306813f6cSJaswinder Singh Rajput 			return "invalid-cache";
30486470930SIngo Molnar 
305e5c59547SJaswinder Singh Rajput 		return event_cache_name(cache_type, cache_op, cache_result);
30686470930SIngo Molnar 	}
30786470930SIngo Molnar 
30886470930SIngo Molnar 	case PERF_TYPE_SOFTWARE:
309f4dbfa8fSPeter Zijlstra 		if (config < PERF_COUNT_SW_MAX)
31086470930SIngo Molnar 			return sw_event_names[config];
31186470930SIngo Molnar 		return "unknown-software";
31286470930SIngo Molnar 
313f6bdafefSJason Baron 	case PERF_TYPE_TRACEPOINT:
314f6bdafefSJason Baron 		return tracepoint_id_to_name(config);
315f6bdafefSJason Baron 
31686470930SIngo Molnar 	default:
31786470930SIngo Molnar 		break;
31886470930SIngo Molnar 	}
31986470930SIngo Molnar 
32086470930SIngo Molnar 	return "unknown";
32186470930SIngo Molnar }
32286470930SIngo Molnar 
32383a0944fSIngo Molnar static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int size)
32486470930SIngo Molnar {
32586470930SIngo Molnar 	int i, j;
32661c45981SPaul Mackerras 	int n, longest = -1;
32786470930SIngo Molnar 
32886470930SIngo Molnar 	for (i = 0; i < size; i++) {
32961c45981SPaul Mackerras 		for (j = 0; j < MAX_ALIASES && names[i][j]; j++) {
33061c45981SPaul Mackerras 			n = strlen(names[i][j]);
33161c45981SPaul Mackerras 			if (n > longest && !strncasecmp(*str, names[i][j], n))
33261c45981SPaul Mackerras 				longest = n;
33361c45981SPaul Mackerras 		}
33461c45981SPaul Mackerras 		if (longest > 0) {
33561c45981SPaul Mackerras 			*str += longest;
33686470930SIngo Molnar 			return i;
33786470930SIngo Molnar 		}
33886470930SIngo Molnar 	}
33986470930SIngo Molnar 
3408953645fSIngo Molnar 	return -1;
34186470930SIngo Molnar }
34286470930SIngo Molnar 
343bcd3279fSFrederic Weisbecker static enum event_result
344cdd6c482SIngo Molnar parse_generic_hw_event(const char **str, struct perf_event_attr *attr)
34586470930SIngo Molnar {
34661c45981SPaul Mackerras 	const char *s = *str;
34761c45981SPaul Mackerras 	int cache_type = -1, cache_op = -1, cache_result = -1;
34886470930SIngo Molnar 
34961c45981SPaul Mackerras 	cache_type = parse_aliases(&s, hw_cache, PERF_COUNT_HW_CACHE_MAX);
35086470930SIngo Molnar 	/*
35186470930SIngo Molnar 	 * No fallback - if we cannot get a clear cache type
35286470930SIngo Molnar 	 * then bail out:
35386470930SIngo Molnar 	 */
35486470930SIngo Molnar 	if (cache_type == -1)
355bcd3279fSFrederic Weisbecker 		return EVT_FAILED;
35686470930SIngo Molnar 
35761c45981SPaul Mackerras 	while ((cache_op == -1 || cache_result == -1) && *s == '-') {
35861c45981SPaul Mackerras 		++s;
35961c45981SPaul Mackerras 
36061c45981SPaul Mackerras 		if (cache_op == -1) {
36161c45981SPaul Mackerras 			cache_op = parse_aliases(&s, hw_cache_op,
36261c45981SPaul Mackerras 						PERF_COUNT_HW_CACHE_OP_MAX);
36361c45981SPaul Mackerras 			if (cache_op >= 0) {
36461c45981SPaul Mackerras 				if (!is_cache_op_valid(cache_type, cache_op))
36561c45981SPaul Mackerras 					return 0;
36661c45981SPaul Mackerras 				continue;
36761c45981SPaul Mackerras 			}
36861c45981SPaul Mackerras 		}
36961c45981SPaul Mackerras 
37061c45981SPaul Mackerras 		if (cache_result == -1) {
37161c45981SPaul Mackerras 			cache_result = parse_aliases(&s, hw_cache_result,
37261c45981SPaul Mackerras 						PERF_COUNT_HW_CACHE_RESULT_MAX);
37361c45981SPaul Mackerras 			if (cache_result >= 0)
37461c45981SPaul Mackerras 				continue;
37561c45981SPaul Mackerras 		}
37661c45981SPaul Mackerras 
37761c45981SPaul Mackerras 		/*
37861c45981SPaul Mackerras 		 * Can't parse this as a cache op or result, so back up
37961c45981SPaul Mackerras 		 * to the '-'.
38061c45981SPaul Mackerras 		 */
38161c45981SPaul Mackerras 		--s;
38261c45981SPaul Mackerras 		break;
38361c45981SPaul Mackerras 	}
38461c45981SPaul Mackerras 
38586470930SIngo Molnar 	/*
38686470930SIngo Molnar 	 * Fall back to reads:
38786470930SIngo Molnar 	 */
3888953645fSIngo Molnar 	if (cache_op == -1)
3898953645fSIngo Molnar 		cache_op = PERF_COUNT_HW_CACHE_OP_READ;
39086470930SIngo Molnar 
39186470930SIngo Molnar 	/*
39286470930SIngo Molnar 	 * Fall back to accesses:
39386470930SIngo Molnar 	 */
39486470930SIngo Molnar 	if (cache_result == -1)
39586470930SIngo Molnar 		cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS;
39686470930SIngo Molnar 
39786470930SIngo Molnar 	attr->config = cache_type | (cache_op << 8) | (cache_result << 16);
39886470930SIngo Molnar 	attr->type = PERF_TYPE_HW_CACHE;
39986470930SIngo Molnar 
40061c45981SPaul Mackerras 	*str = s;
401bcd3279fSFrederic Weisbecker 	return EVT_HANDLED;
40286470930SIngo Molnar }
40386470930SIngo Molnar 
404bcd3279fSFrederic Weisbecker static enum event_result
405bcd3279fSFrederic Weisbecker parse_single_tracepoint_event(char *sys_name,
406bcd3279fSFrederic Weisbecker 			      const char *evt_name,
407bcd3279fSFrederic Weisbecker 			      unsigned int evt_length,
408bcd3279fSFrederic Weisbecker 			      char *flags,
409cdd6c482SIngo Molnar 			      struct perf_event_attr *attr,
410bcd3279fSFrederic Weisbecker 			      const char **strp)
411bcd3279fSFrederic Weisbecker {
412bcd3279fSFrederic Weisbecker 	char evt_path[MAXPATHLEN];
413bcd3279fSFrederic Weisbecker 	char id_buf[4];
414bcd3279fSFrederic Weisbecker 	u64 id;
415bcd3279fSFrederic Weisbecker 	int fd;
416bcd3279fSFrederic Weisbecker 
417bcd3279fSFrederic Weisbecker 	if (flags) {
4181281a49bSLi Zefan 		if (!strncmp(flags, "record", strlen(flags))) {
419bcd3279fSFrederic Weisbecker 			attr->sample_type |= PERF_SAMPLE_RAW;
4201281a49bSLi Zefan 			attr->sample_type |= PERF_SAMPLE_TIME;
4211281a49bSLi Zefan 			attr->sample_type |= PERF_SAMPLE_CPU;
4221281a49bSLi Zefan 		}
423bcd3279fSFrederic Weisbecker 	}
424bcd3279fSFrederic Weisbecker 
425bcd3279fSFrederic Weisbecker 	snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
426bcd3279fSFrederic Weisbecker 		 sys_name, evt_name);
427bcd3279fSFrederic Weisbecker 
428bcd3279fSFrederic Weisbecker 	fd = open(evt_path, O_RDONLY);
429bcd3279fSFrederic Weisbecker 	if (fd < 0)
430bcd3279fSFrederic Weisbecker 		return EVT_FAILED;
431bcd3279fSFrederic Weisbecker 
432bcd3279fSFrederic Weisbecker 	if (read(fd, id_buf, sizeof(id_buf)) < 0) {
433bcd3279fSFrederic Weisbecker 		close(fd);
434bcd3279fSFrederic Weisbecker 		return EVT_FAILED;
435bcd3279fSFrederic Weisbecker 	}
436bcd3279fSFrederic Weisbecker 
437bcd3279fSFrederic Weisbecker 	close(fd);
438bcd3279fSFrederic Weisbecker 	id = atoll(id_buf);
439bcd3279fSFrederic Weisbecker 	attr->config = id;
440bcd3279fSFrederic Weisbecker 	attr->type = PERF_TYPE_TRACEPOINT;
441bcd3279fSFrederic Weisbecker 	*strp = evt_name + evt_length;
442bcd3279fSFrederic Weisbecker 
443bcd3279fSFrederic Weisbecker 	return EVT_HANDLED;
444bcd3279fSFrederic Weisbecker }
445bcd3279fSFrederic Weisbecker 
446bcd3279fSFrederic Weisbecker /* sys + ':' + event + ':' + flags*/
447bcd3279fSFrederic Weisbecker #define MAX_EVOPT_LEN	(MAX_EVENT_LENGTH * 2 + 2 + 128)
448bcd3279fSFrederic Weisbecker static enum event_result
449bcd3279fSFrederic Weisbecker parse_subsystem_tracepoint_event(char *sys_name, char *flags)
450bcd3279fSFrederic Weisbecker {
451bcd3279fSFrederic Weisbecker 	char evt_path[MAXPATHLEN];
452bcd3279fSFrederic Weisbecker 	struct dirent *evt_ent;
453bcd3279fSFrederic Weisbecker 	DIR *evt_dir;
454bcd3279fSFrederic Weisbecker 
455bcd3279fSFrederic Weisbecker 	snprintf(evt_path, MAXPATHLEN, "%s/%s", debugfs_path, sys_name);
456bcd3279fSFrederic Weisbecker 	evt_dir = opendir(evt_path);
457bcd3279fSFrederic Weisbecker 
458bcd3279fSFrederic Weisbecker 	if (!evt_dir) {
459bcd3279fSFrederic Weisbecker 		perror("Can't open event dir");
460bcd3279fSFrederic Weisbecker 		return EVT_FAILED;
461bcd3279fSFrederic Weisbecker 	}
462bcd3279fSFrederic Weisbecker 
463bcd3279fSFrederic Weisbecker 	while ((evt_ent = readdir(evt_dir))) {
464bcd3279fSFrederic Weisbecker 		char event_opt[MAX_EVOPT_LEN + 1];
465bcd3279fSFrederic Weisbecker 		int len;
466bcd3279fSFrederic Weisbecker 		unsigned int rem = MAX_EVOPT_LEN;
467bcd3279fSFrederic Weisbecker 
468bcd3279fSFrederic Weisbecker 		if (!strcmp(evt_ent->d_name, ".")
469bcd3279fSFrederic Weisbecker 		    || !strcmp(evt_ent->d_name, "..")
470bcd3279fSFrederic Weisbecker 		    || !strcmp(evt_ent->d_name, "enable")
471bcd3279fSFrederic Weisbecker 		    || !strcmp(evt_ent->d_name, "filter"))
472bcd3279fSFrederic Weisbecker 			continue;
473bcd3279fSFrederic Weisbecker 
474bcd3279fSFrederic Weisbecker 		len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s", sys_name,
475bcd3279fSFrederic Weisbecker 			       evt_ent->d_name);
476bcd3279fSFrederic Weisbecker 		if (len < 0)
477bcd3279fSFrederic Weisbecker 			return EVT_FAILED;
478bcd3279fSFrederic Weisbecker 
479bcd3279fSFrederic Weisbecker 		rem -= len;
480bcd3279fSFrederic Weisbecker 		if (flags) {
481bcd3279fSFrederic Weisbecker 			if (rem < strlen(flags) + 1)
482bcd3279fSFrederic Weisbecker 				return EVT_FAILED;
483bcd3279fSFrederic Weisbecker 
484bcd3279fSFrederic Weisbecker 			strcat(event_opt, ":");
485bcd3279fSFrederic Weisbecker 			strcat(event_opt, flags);
486bcd3279fSFrederic Weisbecker 		}
487bcd3279fSFrederic Weisbecker 
488bcd3279fSFrederic Weisbecker 		if (parse_events(NULL, event_opt, 0))
489bcd3279fSFrederic Weisbecker 			return EVT_FAILED;
490bcd3279fSFrederic Weisbecker 	}
491bcd3279fSFrederic Weisbecker 
492bcd3279fSFrederic Weisbecker 	return EVT_HANDLED_ALL;
493bcd3279fSFrederic Weisbecker }
494bcd3279fSFrederic Weisbecker 
495bcd3279fSFrederic Weisbecker 
496bcd3279fSFrederic Weisbecker static enum event_result parse_tracepoint_event(const char **strp,
497cdd6c482SIngo Molnar 				    struct perf_event_attr *attr)
498f6bdafefSJason Baron {
499f6bdafefSJason Baron 	const char *evt_name;
5003a9f131fSFrederic Weisbecker 	char *flags;
501f6bdafefSJason Baron 	char sys_name[MAX_EVENT_LENGTH];
502f6bdafefSJason Baron 	unsigned int sys_length, evt_length;
503f6bdafefSJason Baron 
504*549104f2SClark Williams 	if (debugfs_valid_mountpoint(debugfs_path))
505f6bdafefSJason Baron 		return 0;
506f6bdafefSJason Baron 
507f6bdafefSJason Baron 	evt_name = strchr(*strp, ':');
508f6bdafefSJason Baron 	if (!evt_name)
509bcd3279fSFrederic Weisbecker 		return EVT_FAILED;
510f6bdafefSJason Baron 
511f6bdafefSJason Baron 	sys_length = evt_name - *strp;
512f6bdafefSJason Baron 	if (sys_length >= MAX_EVENT_LENGTH)
513f6bdafefSJason Baron 		return 0;
514f6bdafefSJason Baron 
515f6bdafefSJason Baron 	strncpy(sys_name, *strp, sys_length);
516f6bdafefSJason Baron 	sys_name[sys_length] = '\0';
517f6bdafefSJason Baron 	evt_name = evt_name + 1;
5183a9f131fSFrederic Weisbecker 
5193a9f131fSFrederic Weisbecker 	flags = strchr(evt_name, ':');
5203a9f131fSFrederic Weisbecker 	if (flags) {
5211fc35b29SIngo Molnar 		/* split it out: */
5221fc35b29SIngo Molnar 		evt_name = strndup(evt_name, flags - evt_name);
5233a9f131fSFrederic Weisbecker 		flags++;
5243a9f131fSFrederic Weisbecker 	}
5253a9f131fSFrederic Weisbecker 
526f6bdafefSJason Baron 	evt_length = strlen(evt_name);
527f6bdafefSJason Baron 	if (evt_length >= MAX_EVENT_LENGTH)
528bcd3279fSFrederic Weisbecker 		return EVT_FAILED;
529f6bdafefSJason Baron 
530bcd3279fSFrederic Weisbecker 	if (!strcmp(evt_name, "*")) {
531f6bdafefSJason Baron 		*strp = evt_name + evt_length;
532bcd3279fSFrederic Weisbecker 		return parse_subsystem_tracepoint_event(sys_name, flags);
533bcd3279fSFrederic Weisbecker 	} else
534bcd3279fSFrederic Weisbecker 		return parse_single_tracepoint_event(sys_name, evt_name,
535bcd3279fSFrederic Weisbecker 						     evt_length, flags,
536bcd3279fSFrederic Weisbecker 						     attr, strp);
537f6bdafefSJason Baron }
538f6bdafefSJason Baron 
53974d5b588SJaswinder Singh Rajput static int check_events(const char *str, unsigned int i)
54074d5b588SJaswinder Singh Rajput {
54161c45981SPaul Mackerras 	int n;
54274d5b588SJaswinder Singh Rajput 
54361c45981SPaul Mackerras 	n = strlen(event_symbols[i].symbol);
54461c45981SPaul Mackerras 	if (!strncmp(str, event_symbols[i].symbol, n))
54561c45981SPaul Mackerras 		return n;
54661c45981SPaul Mackerras 
54761c45981SPaul Mackerras 	n = strlen(event_symbols[i].alias);
54861c45981SPaul Mackerras 	if (n)
54961c45981SPaul Mackerras 		if (!strncmp(str, event_symbols[i].alias, n))
55061c45981SPaul Mackerras 			return n;
55161c45981SPaul Mackerras 	return 0;
55261c45981SPaul Mackerras }
55361c45981SPaul Mackerras 
554bcd3279fSFrederic Weisbecker static enum event_result
555cdd6c482SIngo Molnar parse_symbolic_event(const char **strp, struct perf_event_attr *attr)
55661c45981SPaul Mackerras {
55761c45981SPaul Mackerras 	const char *str = *strp;
55861c45981SPaul Mackerras 	unsigned int i;
55961c45981SPaul Mackerras 	int n;
56061c45981SPaul Mackerras 
56161c45981SPaul Mackerras 	for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
56261c45981SPaul Mackerras 		n = check_events(str, i);
56361c45981SPaul Mackerras 		if (n > 0) {
56461c45981SPaul Mackerras 			attr->type = event_symbols[i].type;
56561c45981SPaul Mackerras 			attr->config = event_symbols[i].config;
56661c45981SPaul Mackerras 			*strp = str + n;
567bcd3279fSFrederic Weisbecker 			return EVT_HANDLED;
56861c45981SPaul Mackerras 		}
56961c45981SPaul Mackerras 	}
570bcd3279fSFrederic Weisbecker 	return EVT_FAILED;
57161c45981SPaul Mackerras }
57261c45981SPaul Mackerras 
573bcd3279fSFrederic Weisbecker static enum event_result
574cdd6c482SIngo Molnar parse_raw_event(const char **strp, struct perf_event_attr *attr)
57561c45981SPaul Mackerras {
57661c45981SPaul Mackerras 	const char *str = *strp;
57761c45981SPaul Mackerras 	u64 config;
57861c45981SPaul Mackerras 	int n;
57961c45981SPaul Mackerras 
58061c45981SPaul Mackerras 	if (*str != 'r')
581bcd3279fSFrederic Weisbecker 		return EVT_FAILED;
58261c45981SPaul Mackerras 	n = hex2u64(str + 1, &config);
58361c45981SPaul Mackerras 	if (n > 0) {
58461c45981SPaul Mackerras 		*strp = str + n + 1;
58561c45981SPaul Mackerras 		attr->type = PERF_TYPE_RAW;
58661c45981SPaul Mackerras 		attr->config = config;
587bcd3279fSFrederic Weisbecker 		return EVT_HANDLED;
58861c45981SPaul Mackerras 	}
589bcd3279fSFrederic Weisbecker 	return EVT_FAILED;
59061c45981SPaul Mackerras }
59161c45981SPaul Mackerras 
592bcd3279fSFrederic Weisbecker static enum event_result
593cdd6c482SIngo Molnar parse_numeric_event(const char **strp, struct perf_event_attr *attr)
59461c45981SPaul Mackerras {
59561c45981SPaul Mackerras 	const char *str = *strp;
59661c45981SPaul Mackerras 	char *endp;
59761c45981SPaul Mackerras 	unsigned long type;
59861c45981SPaul Mackerras 	u64 config;
59961c45981SPaul Mackerras 
60061c45981SPaul Mackerras 	type = strtoul(str, &endp, 0);
60161c45981SPaul Mackerras 	if (endp > str && type < PERF_TYPE_MAX && *endp == ':') {
60261c45981SPaul Mackerras 		str = endp + 1;
60361c45981SPaul Mackerras 		config = strtoul(str, &endp, 0);
60461c45981SPaul Mackerras 		if (endp > str) {
60561c45981SPaul Mackerras 			attr->type = type;
60661c45981SPaul Mackerras 			attr->config = config;
60761c45981SPaul Mackerras 			*strp = endp;
608bcd3279fSFrederic Weisbecker 			return EVT_HANDLED;
60961c45981SPaul Mackerras 		}
61061c45981SPaul Mackerras 	}
611bcd3279fSFrederic Weisbecker 	return EVT_FAILED;
61261c45981SPaul Mackerras }
61361c45981SPaul Mackerras 
614bcd3279fSFrederic Weisbecker static enum event_result
615cdd6c482SIngo Molnar parse_event_modifier(const char **strp, struct perf_event_attr *attr)
61661c45981SPaul Mackerras {
61761c45981SPaul Mackerras 	const char *str = *strp;
61861c45981SPaul Mackerras 	int eu = 1, ek = 1, eh = 1;
61961c45981SPaul Mackerras 
62061c45981SPaul Mackerras 	if (*str++ != ':')
62161c45981SPaul Mackerras 		return 0;
62261c45981SPaul Mackerras 	while (*str) {
62361c45981SPaul Mackerras 		if (*str == 'u')
62461c45981SPaul Mackerras 			eu = 0;
62561c45981SPaul Mackerras 		else if (*str == 'k')
62661c45981SPaul Mackerras 			ek = 0;
62761c45981SPaul Mackerras 		else if (*str == 'h')
62861c45981SPaul Mackerras 			eh = 0;
62961c45981SPaul Mackerras 		else
63061c45981SPaul Mackerras 			break;
63161c45981SPaul Mackerras 		++str;
63261c45981SPaul Mackerras 	}
63361c45981SPaul Mackerras 	if (str >= *strp + 2) {
63461c45981SPaul Mackerras 		*strp = str;
63561c45981SPaul Mackerras 		attr->exclude_user   = eu;
63661c45981SPaul Mackerras 		attr->exclude_kernel = ek;
63761c45981SPaul Mackerras 		attr->exclude_hv     = eh;
63861c45981SPaul Mackerras 		return 1;
63961c45981SPaul Mackerras 	}
64074d5b588SJaswinder Singh Rajput 	return 0;
64174d5b588SJaswinder Singh Rajput }
64274d5b588SJaswinder Singh Rajput 
64386470930SIngo Molnar /*
64486470930SIngo Molnar  * Each event can have multiple symbolic names.
64586470930SIngo Molnar  * Symbolic names are (almost) exactly matched.
64686470930SIngo Molnar  */
647bcd3279fSFrederic Weisbecker static enum event_result
648cdd6c482SIngo Molnar parse_event_symbols(const char **str, struct perf_event_attr *attr)
64986470930SIngo Molnar {
650bcd3279fSFrederic Weisbecker 	enum event_result ret;
65186470930SIngo Molnar 
652bcd3279fSFrederic Weisbecker 	ret = parse_tracepoint_event(str, attr);
653bcd3279fSFrederic Weisbecker 	if (ret != EVT_FAILED)
654bcd3279fSFrederic Weisbecker 		goto modifier;
655bcd3279fSFrederic Weisbecker 
656bcd3279fSFrederic Weisbecker 	ret = parse_raw_event(str, attr);
657bcd3279fSFrederic Weisbecker 	if (ret != EVT_FAILED)
658bcd3279fSFrederic Weisbecker 		goto modifier;
659bcd3279fSFrederic Weisbecker 
660bcd3279fSFrederic Weisbecker 	ret = parse_numeric_event(str, attr);
661bcd3279fSFrederic Weisbecker 	if (ret != EVT_FAILED)
662bcd3279fSFrederic Weisbecker 		goto modifier;
663bcd3279fSFrederic Weisbecker 
664bcd3279fSFrederic Weisbecker 	ret = parse_symbolic_event(str, attr);
665bcd3279fSFrederic Weisbecker 	if (ret != EVT_FAILED)
666bcd3279fSFrederic Weisbecker 		goto modifier;
667bcd3279fSFrederic Weisbecker 
668bcd3279fSFrederic Weisbecker 	ret = parse_generic_hw_event(str, attr);
669bcd3279fSFrederic Weisbecker 	if (ret != EVT_FAILED)
670bcd3279fSFrederic Weisbecker 		goto modifier;
671bcd3279fSFrederic Weisbecker 
67285df6f68SMarti Raudsepp 	fprintf(stderr, "invalid or unsupported event: '%s'\n", *str);
67385df6f68SMarti Raudsepp 	fprintf(stderr, "Run 'perf list' for a list of valid events\n");
674bcd3279fSFrederic Weisbecker 	return EVT_FAILED;
675bcd3279fSFrederic Weisbecker 
676bcd3279fSFrederic Weisbecker modifier:
67761c45981SPaul Mackerras 	parse_event_modifier(str, attr);
67886470930SIngo Molnar 
679bcd3279fSFrederic Weisbecker 	return ret;
68086470930SIngo Molnar }
68186470930SIngo Molnar 
6828755a8f2SArjan van de Ven static void store_event_type(const char *orgname)
6838755a8f2SArjan van de Ven {
6848755a8f2SArjan van de Ven 	char filename[PATH_MAX], *c;
6858755a8f2SArjan van de Ven 	FILE *file;
6868755a8f2SArjan van de Ven 	int id;
6878755a8f2SArjan van de Ven 
68863c9e01eSAshwin Chaugule 	sprintf(filename, "%s/", debugfs_path);
68963c9e01eSAshwin Chaugule 	strncat(filename, orgname, strlen(orgname));
69063c9e01eSAshwin Chaugule 	strcat(filename, "/id");
69163c9e01eSAshwin Chaugule 
6928755a8f2SArjan van de Ven 	c = strchr(filename, ':');
6938755a8f2SArjan van de Ven 	if (c)
6948755a8f2SArjan van de Ven 		*c = '/';
6958755a8f2SArjan van de Ven 
6968755a8f2SArjan van de Ven 	file = fopen(filename, "r");
6978755a8f2SArjan van de Ven 	if (!file)
6988755a8f2SArjan van de Ven 		return;
6998755a8f2SArjan van de Ven 	if (fscanf(file, "%i", &id) < 1)
7008755a8f2SArjan van de Ven 		die("cannot store event ID");
7018755a8f2SArjan van de Ven 	fclose(file);
7028755a8f2SArjan van de Ven 	perf_header__push_event(id, orgname);
7038755a8f2SArjan van de Ven }
7048755a8f2SArjan van de Ven 
705f37a291cSIngo Molnar int parse_events(const struct option *opt __used, const char *str, int unset __used)
70686470930SIngo Molnar {
707cdd6c482SIngo Molnar 	struct perf_event_attr attr;
708bcd3279fSFrederic Weisbecker 	enum event_result ret;
70986470930SIngo Molnar 
7108755a8f2SArjan van de Ven 	if (strchr(str, ':'))
7118755a8f2SArjan van de Ven 		store_event_type(str);
7128755a8f2SArjan van de Ven 
71361c45981SPaul Mackerras 	for (;;) {
71486470930SIngo Molnar 		if (nr_counters == MAX_COUNTERS)
71586470930SIngo Molnar 			return -1;
71686470930SIngo Molnar 
71761c45981SPaul Mackerras 		memset(&attr, 0, sizeof(attr));
718bcd3279fSFrederic Weisbecker 		ret = parse_event_symbols(&str, &attr);
719bcd3279fSFrederic Weisbecker 		if (ret == EVT_FAILED)
72061c45981SPaul Mackerras 			return -1;
72161c45981SPaul Mackerras 
72261c45981SPaul Mackerras 		if (!(*str == 0 || *str == ',' || isspace(*str)))
72361c45981SPaul Mackerras 			return -1;
72486470930SIngo Molnar 
725bcd3279fSFrederic Weisbecker 		if (ret != EVT_HANDLED_ALL) {
72686470930SIngo Molnar 			attrs[nr_counters] = attr;
72786470930SIngo Molnar 			nr_counters++;
728bcd3279fSFrederic Weisbecker 		}
72986470930SIngo Molnar 
73061c45981SPaul Mackerras 		if (*str == 0)
73161c45981SPaul Mackerras 			break;
73261c45981SPaul Mackerras 		if (*str == ',')
73361c45981SPaul Mackerras 			++str;
73461c45981SPaul Mackerras 		while (isspace(*str))
73561c45981SPaul Mackerras 			++str;
73686470930SIngo Molnar 	}
73786470930SIngo Molnar 
73886470930SIngo Molnar 	return 0;
73986470930SIngo Molnar }
74086470930SIngo Molnar 
741c171b552SLi Zefan int parse_filter(const struct option *opt __used, const char *str,
742c171b552SLi Zefan 		 int unset __used)
743c171b552SLi Zefan {
744c171b552SLi Zefan 	int i = nr_counters - 1;
745c171b552SLi Zefan 	int len = strlen(str);
746c171b552SLi Zefan 
747c171b552SLi Zefan 	if (i < 0 || attrs[i].type != PERF_TYPE_TRACEPOINT) {
748c171b552SLi Zefan 		fprintf(stderr,
749c171b552SLi Zefan 			"-F option should follow a -e tracepoint option\n");
750c171b552SLi Zefan 		return -1;
751c171b552SLi Zefan 	}
752c171b552SLi Zefan 
753c171b552SLi Zefan 	filters[i] = malloc(len + 1);
754c171b552SLi Zefan 	if (!filters[i]) {
755c171b552SLi Zefan 		fprintf(stderr, "not enough memory to hold filter string\n");
756c171b552SLi Zefan 		return -1;
757c171b552SLi Zefan 	}
758c171b552SLi Zefan 	strcpy(filters[i], str);
759c171b552SLi Zefan 
760c171b552SLi Zefan 	return 0;
761c171b552SLi Zefan }
762c171b552SLi Zefan 
76386470930SIngo Molnar static const char * const event_type_descriptors[] = {
76486470930SIngo Molnar 	"",
76586470930SIngo Molnar 	"Hardware event",
76686470930SIngo Molnar 	"Software event",
76786470930SIngo Molnar 	"Tracepoint event",
76886470930SIngo Molnar 	"Hardware cache event",
76986470930SIngo Molnar };
77086470930SIngo Molnar 
77186470930SIngo Molnar /*
772f6bdafefSJason Baron  * Print the events from <debugfs_mount_point>/tracing/events
773f6bdafefSJason Baron  */
774f6bdafefSJason Baron 
775f6bdafefSJason Baron static void print_tracepoint_events(void)
776f6bdafefSJason Baron {
777f6bdafefSJason Baron 	DIR *sys_dir, *evt_dir;
778f6bdafefSJason Baron 	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
779f6bdafefSJason Baron 	char evt_path[MAXPATHLEN];
780725b1368SEric Dumazet 	char dir_path[MAXPATHLEN];
781f6bdafefSJason Baron 
782*549104f2SClark Williams 	if (debugfs_valid_mountpoint(debugfs_path))
783f6bdafefSJason Baron 		return;
784f6bdafefSJason Baron 
7855beeded1SJason Baron 	sys_dir = opendir(debugfs_path);
786f6bdafefSJason Baron 	if (!sys_dir)
787725b1368SEric Dumazet 		return;
788f6bdafefSJason Baron 
7896b58e7f1SUlrich Drepper 	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
790725b1368SEric Dumazet 
791725b1368SEric Dumazet 		snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
792725b1368SEric Dumazet 			 sys_dirent.d_name);
793725b1368SEric Dumazet 		evt_dir = opendir(dir_path);
794725b1368SEric Dumazet 		if (!evt_dir)
7956b58e7f1SUlrich Drepper 			continue;
796725b1368SEric Dumazet 
7976b58e7f1SUlrich Drepper 		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
798f6bdafefSJason Baron 			snprintf(evt_path, MAXPATHLEN, "%s:%s",
799f6bdafefSJason Baron 				 sys_dirent.d_name, evt_dirent.d_name);
800689d3018SMarti Raudsepp 			printf("  %-42s [%s]\n", evt_path,
801f6bdafefSJason Baron 				event_type_descriptors[PERF_TYPE_TRACEPOINT+1]);
802f6bdafefSJason Baron 		}
803f6bdafefSJason Baron 		closedir(evt_dir);
804f6bdafefSJason Baron 	}
805f6bdafefSJason Baron 	closedir(sys_dir);
806f6bdafefSJason Baron }
807f6bdafefSJason Baron 
808f6bdafefSJason Baron /*
80986470930SIngo Molnar  * Print the help text for the event symbols:
81086470930SIngo Molnar  */
81186470930SIngo Molnar void print_events(void)
81286470930SIngo Molnar {
81386470930SIngo Molnar 	struct event_symbol *syms = event_symbols;
81473c24cb8SJaswinder Singh Rajput 	unsigned int i, type, op, prev_type = -1;
81574d5b588SJaswinder Singh Rajput 	char name[40];
81686470930SIngo Molnar 
817689d3018SMarti Raudsepp 	printf("\n");
818689d3018SMarti Raudsepp 	printf("List of pre-defined events (to be used in -e):\n");
81986470930SIngo Molnar 
82086470930SIngo Molnar 	for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
82186470930SIngo Molnar 		type = syms->type + 1;
82223cdb5d5SRoel Kluin 		if (type >= ARRAY_SIZE(event_type_descriptors))
82386470930SIngo Molnar 			type = 0;
82486470930SIngo Molnar 
82586470930SIngo Molnar 		if (type != prev_type)
826689d3018SMarti Raudsepp 			printf("\n");
82786470930SIngo Molnar 
82874d5b588SJaswinder Singh Rajput 		if (strlen(syms->alias))
82974d5b588SJaswinder Singh Rajput 			sprintf(name, "%s OR %s", syms->symbol, syms->alias);
83074d5b588SJaswinder Singh Rajput 		else
83174d5b588SJaswinder Singh Rajput 			strcpy(name, syms->symbol);
832689d3018SMarti Raudsepp 		printf("  %-42s [%s]\n", name,
83386470930SIngo Molnar 			event_type_descriptors[type]);
83486470930SIngo Molnar 
83586470930SIngo Molnar 		prev_type = type;
83686470930SIngo Molnar 	}
83786470930SIngo Molnar 
838689d3018SMarti Raudsepp 	printf("\n");
83973c24cb8SJaswinder Singh Rajput 	for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
84073c24cb8SJaswinder Singh Rajput 		for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
84173c24cb8SJaswinder Singh Rajput 			/* skip invalid cache type */
84273c24cb8SJaswinder Singh Rajput 			if (!is_cache_op_valid(type, op))
84373c24cb8SJaswinder Singh Rajput 				continue;
84473c24cb8SJaswinder Singh Rajput 
84573c24cb8SJaswinder Singh Rajput 			for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
846689d3018SMarti Raudsepp 				printf("  %-42s [%s]\n",
84773c24cb8SJaswinder Singh Rajput 					event_cache_name(type, op, i),
84873c24cb8SJaswinder Singh Rajput 					event_type_descriptors[4]);
84973c24cb8SJaswinder Singh Rajput 			}
85073c24cb8SJaswinder Singh Rajput 		}
85173c24cb8SJaswinder Singh Rajput 	}
85273c24cb8SJaswinder Singh Rajput 
853689d3018SMarti Raudsepp 	printf("\n");
854689d3018SMarti Raudsepp 	printf("  %-42s [raw hardware event descriptor]\n",
85586470930SIngo Molnar 		"rNNN");
856689d3018SMarti Raudsepp 	printf("\n");
85786470930SIngo Molnar 
858f6bdafefSJason Baron 	print_tracepoint_events();
859f6bdafefSJason Baron 
86086470930SIngo Molnar 	exit(129);
86186470930SIngo Molnar }
862