xref: /linux/tools/perf/util/parse-events.c (revision 63c9e01e1a0dcecc982137d527d44b5ac808b607)
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"
1086470930SIngo Molnar 
1186470930SIngo Molnar int					nr_counters;
1286470930SIngo Molnar 
13cdd6c482SIngo Molnar struct perf_event_attr		attrs[MAX_COUNTERS];
1486470930SIngo Molnar 
1586470930SIngo Molnar struct event_symbol {
169cffa8d5SPaul Mackerras 	u8		type;
179cffa8d5SPaul Mackerras 	u64		config;
1883a0944fSIngo Molnar 	const char	*symbol;
1983a0944fSIngo Molnar 	const char	*alias;
2086470930SIngo Molnar };
2186470930SIngo Molnar 
22bcd3279fSFrederic Weisbecker enum event_result {
23bcd3279fSFrederic Weisbecker 	EVT_FAILED,
24bcd3279fSFrederic Weisbecker 	EVT_HANDLED,
25bcd3279fSFrederic Weisbecker 	EVT_HANDLED_ALL
26bcd3279fSFrederic Weisbecker };
27bcd3279fSFrederic Weisbecker 
285beeded1SJason Baron char debugfs_path[MAXPATHLEN];
295beeded1SJason Baron 
3051e26842SJaswinder Singh Rajput #define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
3151e26842SJaswinder Singh Rajput #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
3286470930SIngo Molnar 
3386470930SIngo Molnar static struct event_symbol event_symbols[] = {
3474d5b588SJaswinder Singh Rajput   { CHW(CPU_CYCLES),		"cpu-cycles",		"cycles"	},
3574d5b588SJaswinder Singh Rajput   { CHW(INSTRUCTIONS),		"instructions",		""		},
3674d5b588SJaswinder Singh Rajput   { CHW(CACHE_REFERENCES),	"cache-references",	""		},
3774d5b588SJaswinder Singh Rajput   { CHW(CACHE_MISSES),		"cache-misses",		""		},
3874d5b588SJaswinder Singh Rajput   { CHW(BRANCH_INSTRUCTIONS),	"branch-instructions",	"branches"	},
3974d5b588SJaswinder Singh Rajput   { CHW(BRANCH_MISSES),		"branch-misses",	""		},
4074d5b588SJaswinder Singh Rajput   { CHW(BUS_CYCLES),		"bus-cycles",		""		},
4186470930SIngo Molnar 
4274d5b588SJaswinder Singh Rajput   { CSW(CPU_CLOCK),		"cpu-clock",		""		},
4374d5b588SJaswinder Singh Rajput   { CSW(TASK_CLOCK),		"task-clock",		""		},
44c0c22dbfSJaswinder Singh Rajput   { CSW(PAGE_FAULTS),		"page-faults",		"faults"	},
4574d5b588SJaswinder Singh Rajput   { CSW(PAGE_FAULTS_MIN),	"minor-faults",		""		},
4674d5b588SJaswinder Singh Rajput   { CSW(PAGE_FAULTS_MAJ),	"major-faults",		""		},
4774d5b588SJaswinder Singh Rajput   { CSW(CONTEXT_SWITCHES),	"context-switches",	"cs"		},
4874d5b588SJaswinder Singh Rajput   { CSW(CPU_MIGRATIONS),	"cpu-migrations",	"migrations"	},
4986470930SIngo Molnar };
5086470930SIngo Molnar 
51cdd6c482SIngo Molnar #define __PERF_EVENT_FIELD(config, name) \
52cdd6c482SIngo Molnar 	((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT)
5386470930SIngo Molnar 
54cdd6c482SIngo Molnar #define PERF_EVENT_RAW(config)	__PERF_EVENT_FIELD(config, RAW)
55cdd6c482SIngo Molnar #define PERF_EVENT_CONFIG(config)	__PERF_EVENT_FIELD(config, CONFIG)
56cdd6c482SIngo Molnar #define PERF_EVENT_TYPE(config)	__PERF_EVENT_FIELD(config, TYPE)
57cdd6c482SIngo Molnar #define PERF_EVENT_ID(config)		__PERF_EVENT_FIELD(config, EVENT)
5886470930SIngo Molnar 
5983a0944fSIngo Molnar static const char *hw_event_names[] = {
6086470930SIngo Molnar 	"cycles",
6186470930SIngo Molnar 	"instructions",
6286470930SIngo Molnar 	"cache-references",
6386470930SIngo Molnar 	"cache-misses",
6486470930SIngo Molnar 	"branches",
6586470930SIngo Molnar 	"branch-misses",
6686470930SIngo Molnar 	"bus-cycles",
6786470930SIngo Molnar };
6886470930SIngo Molnar 
6983a0944fSIngo Molnar static const char *sw_event_names[] = {
7044175b6fSIngo Molnar 	"cpu-clock-msecs",
7144175b6fSIngo Molnar 	"task-clock-msecs",
7286470930SIngo Molnar 	"page-faults",
7386470930SIngo Molnar 	"context-switches",
7486470930SIngo Molnar 	"CPU-migrations",
7586470930SIngo Molnar 	"minor-faults",
7686470930SIngo Molnar 	"major-faults",
7786470930SIngo Molnar };
7886470930SIngo Molnar 
7986470930SIngo Molnar #define MAX_ALIASES 8
8086470930SIngo Molnar 
8183a0944fSIngo Molnar static const char *hw_cache[][MAX_ALIASES] = {
829590b7baSAnton Blanchard  { "L1-dcache",	"l1-d",		"l1d",		"L1-data",		},
839590b7baSAnton Blanchard  { "L1-icache",	"l1-i",		"l1i",		"L1-instruction",	},
84e5c59547SJaswinder Singh Rajput  { "LLC",	"L2"							},
85e5c59547SJaswinder Singh Rajput  { "dTLB",	"d-tlb",	"Data-TLB",				},
86e5c59547SJaswinder Singh Rajput  { "iTLB",	"i-tlb",	"Instruction-TLB",			},
87e5c59547SJaswinder Singh Rajput  { "branch",	"branches",	"bpu",		"btb",		"bpc",	},
8886470930SIngo Molnar };
8986470930SIngo Molnar 
9083a0944fSIngo Molnar static const char *hw_cache_op[][MAX_ALIASES] = {
91e5c59547SJaswinder Singh Rajput  { "load",	"loads",	"read",					},
92e5c59547SJaswinder Singh Rajput  { "store",	"stores",	"write",				},
93e5c59547SJaswinder Singh Rajput  { "prefetch",	"prefetches",	"speculative-read", "speculative-load",	},
9486470930SIngo Molnar };
9586470930SIngo Molnar 
9683a0944fSIngo Molnar static const char *hw_cache_result[][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),
11906813f6cSJaswinder Singh Rajput };
12006813f6cSJaswinder Singh Rajput 
1216b58e7f1SUlrich Drepper #define for_each_subsystem(sys_dir, sys_dirent, sys_next)	       \
122f6bdafefSJason Baron 	while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next)	       \
1236b58e7f1SUlrich Drepper 	if (sys_dirent.d_type == DT_DIR &&				       \
124f6bdafefSJason Baron 	   (strcmp(sys_dirent.d_name, ".")) &&				       \
125f6bdafefSJason Baron 	   (strcmp(sys_dirent.d_name, "..")))
126f6bdafefSJason Baron 
127ae07b63fSPeter Zijlstra static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
128ae07b63fSPeter Zijlstra {
129ae07b63fSPeter Zijlstra 	char evt_path[MAXPATHLEN];
130ae07b63fSPeter Zijlstra 	int fd;
131ae07b63fSPeter Zijlstra 
132ae07b63fSPeter Zijlstra 	snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
133ae07b63fSPeter Zijlstra 			sys_dir->d_name, evt_dir->d_name);
134ae07b63fSPeter Zijlstra 	fd = open(evt_path, O_RDONLY);
135ae07b63fSPeter Zijlstra 	if (fd < 0)
136ae07b63fSPeter Zijlstra 		return -EINVAL;
137ae07b63fSPeter Zijlstra 	close(fd);
138ae07b63fSPeter Zijlstra 
139ae07b63fSPeter Zijlstra 	return 0;
140ae07b63fSPeter Zijlstra }
141ae07b63fSPeter Zijlstra 
1426b58e7f1SUlrich Drepper #define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next)	       \
143f6bdafefSJason Baron 	while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next)        \
1446b58e7f1SUlrich Drepper 	if (evt_dirent.d_type == DT_DIR &&				       \
145f6bdafefSJason Baron 	   (strcmp(evt_dirent.d_name, ".")) &&				       \
146ae07b63fSPeter Zijlstra 	   (strcmp(evt_dirent.d_name, "..")) &&				       \
147ae07b63fSPeter Zijlstra 	   (!tp_event_has_id(&sys_dirent, &evt_dirent)))
148f6bdafefSJason Baron 
149270bbbe8SLi Zefan #define MAX_EVENT_LENGTH 512
150f6bdafefSJason Baron 
1515beeded1SJason Baron int valid_debugfs_mount(const char *debugfs)
152f6bdafefSJason Baron {
153f6bdafefSJason Baron 	struct statfs st_fs;
154f6bdafefSJason Baron 
1555beeded1SJason Baron 	if (statfs(debugfs, &st_fs) < 0)
156f6bdafefSJason Baron 		return -ENOENT;
157f6bdafefSJason Baron 	else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
158f6bdafefSJason Baron 		return -ENOENT;
159f6bdafefSJason Baron 	return 0;
160f6bdafefSJason Baron }
161f6bdafefSJason Baron 
1621ef2ed10SFrederic Weisbecker struct tracepoint_path *tracepoint_id_to_path(u64 config)
163f6bdafefSJason Baron {
1641ef2ed10SFrederic Weisbecker 	struct tracepoint_path *path = NULL;
165f6bdafefSJason Baron 	DIR *sys_dir, *evt_dir;
166f6bdafefSJason Baron 	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
167f6bdafefSJason Baron 	char id_buf[4];
168725b1368SEric Dumazet 	int fd;
169f6bdafefSJason Baron 	u64 id;
170f6bdafefSJason Baron 	char evt_path[MAXPATHLEN];
171725b1368SEric Dumazet 	char dir_path[MAXPATHLEN];
172f6bdafefSJason Baron 
1735beeded1SJason Baron 	if (valid_debugfs_mount(debugfs_path))
1741ef2ed10SFrederic Weisbecker 		return NULL;
175f6bdafefSJason Baron 
1765beeded1SJason Baron 	sys_dir = opendir(debugfs_path);
177f6bdafefSJason Baron 	if (!sys_dir)
178725b1368SEric Dumazet 		return NULL;
179f6bdafefSJason Baron 
1806b58e7f1SUlrich Drepper 	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
181725b1368SEric Dumazet 
182725b1368SEric Dumazet 		snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
183725b1368SEric Dumazet 			 sys_dirent.d_name);
184725b1368SEric Dumazet 		evt_dir = opendir(dir_path);
185725b1368SEric Dumazet 		if (!evt_dir)
1866b58e7f1SUlrich Drepper 			continue;
187725b1368SEric Dumazet 
1886b58e7f1SUlrich Drepper 		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
189725b1368SEric Dumazet 
190725b1368SEric Dumazet 			snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
191f6bdafefSJason Baron 				 evt_dirent.d_name);
192725b1368SEric Dumazet 			fd = open(evt_path, O_RDONLY);
193f6bdafefSJason Baron 			if (fd < 0)
194f6bdafefSJason Baron 				continue;
195f6bdafefSJason Baron 			if (read(fd, id_buf, sizeof(id_buf)) < 0) {
196f6bdafefSJason Baron 				close(fd);
197f6bdafefSJason Baron 				continue;
198f6bdafefSJason Baron 			}
199f6bdafefSJason Baron 			close(fd);
200f6bdafefSJason Baron 			id = atoll(id_buf);
201f6bdafefSJason Baron 			if (id == config) {
202f6bdafefSJason Baron 				closedir(evt_dir);
203f6bdafefSJason Baron 				closedir(sys_dir);
2041ef2ed10SFrederic Weisbecker 				path = calloc(1, sizeof(path));
2051ef2ed10SFrederic Weisbecker 				path->system = malloc(MAX_EVENT_LENGTH);
2061ef2ed10SFrederic Weisbecker 				if (!path->system) {
2071ef2ed10SFrederic Weisbecker 					free(path);
2081ef2ed10SFrederic Weisbecker 					return NULL;
2091ef2ed10SFrederic Weisbecker 				}
2101ef2ed10SFrederic Weisbecker 				path->name = malloc(MAX_EVENT_LENGTH);
2111ef2ed10SFrederic Weisbecker 				if (!path->name) {
2121ef2ed10SFrederic Weisbecker 					free(path->system);
2131ef2ed10SFrederic Weisbecker 					free(path);
2141ef2ed10SFrederic Weisbecker 					return NULL;
2151ef2ed10SFrederic Weisbecker 				}
2161ef2ed10SFrederic Weisbecker 				strncpy(path->system, sys_dirent.d_name,
2171ef2ed10SFrederic Weisbecker 					MAX_EVENT_LENGTH);
2181ef2ed10SFrederic Weisbecker 				strncpy(path->name, evt_dirent.d_name,
2191ef2ed10SFrederic Weisbecker 					MAX_EVENT_LENGTH);
2201ef2ed10SFrederic Weisbecker 				return path;
221f6bdafefSJason Baron 			}
222f6bdafefSJason Baron 		}
223f6bdafefSJason Baron 		closedir(evt_dir);
224f6bdafefSJason Baron 	}
225f6bdafefSJason Baron 
226f6bdafefSJason Baron 	closedir(sys_dir);
2271ef2ed10SFrederic Weisbecker 	return NULL;
2281ef2ed10SFrederic Weisbecker }
2291ef2ed10SFrederic Weisbecker 
2301ef2ed10SFrederic Weisbecker #define TP_PATH_LEN (MAX_EVENT_LENGTH * 2 + 1)
2311ef2ed10SFrederic Weisbecker static const char *tracepoint_id_to_name(u64 config)
2321ef2ed10SFrederic Weisbecker {
2331ef2ed10SFrederic Weisbecker 	static char buf[TP_PATH_LEN];
2341ef2ed10SFrederic Weisbecker 	struct tracepoint_path *path;
2351ef2ed10SFrederic Weisbecker 
2361ef2ed10SFrederic Weisbecker 	path = tracepoint_id_to_path(config);
2371ef2ed10SFrederic Weisbecker 	if (path) {
2381ef2ed10SFrederic Weisbecker 		snprintf(buf, TP_PATH_LEN, "%s:%s", path->system, path->name);
2391ef2ed10SFrederic Weisbecker 		free(path->name);
2401ef2ed10SFrederic Weisbecker 		free(path->system);
2411ef2ed10SFrederic Weisbecker 		free(path);
2421ef2ed10SFrederic Weisbecker 	} else
2431ef2ed10SFrederic Weisbecker 		snprintf(buf, TP_PATH_LEN, "%s:%s", "unknown", "unknown");
2441ef2ed10SFrederic Weisbecker 
2451ef2ed10SFrederic Weisbecker 	return buf;
246f6bdafefSJason Baron }
247f6bdafefSJason Baron 
24806813f6cSJaswinder Singh Rajput static int is_cache_op_valid(u8 cache_type, u8 cache_op)
24906813f6cSJaswinder Singh Rajput {
25006813f6cSJaswinder Singh Rajput 	if (hw_cache_stat[cache_type] & COP(cache_op))
25106813f6cSJaswinder Singh Rajput 		return 1;	/* valid */
25206813f6cSJaswinder Singh Rajput 	else
25306813f6cSJaswinder Singh Rajput 		return 0;	/* invalid */
25406813f6cSJaswinder Singh Rajput }
25506813f6cSJaswinder Singh Rajput 
256e5c59547SJaswinder Singh Rajput static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
257e5c59547SJaswinder Singh Rajput {
258e5c59547SJaswinder Singh Rajput 	static char name[50];
259e5c59547SJaswinder Singh Rajput 
260e5c59547SJaswinder Singh Rajput 	if (cache_result) {
261e5c59547SJaswinder Singh Rajput 		sprintf(name, "%s-%s-%s", hw_cache[cache_type][0],
262e5c59547SJaswinder Singh Rajput 			hw_cache_op[cache_op][0],
263e5c59547SJaswinder Singh Rajput 			hw_cache_result[cache_result][0]);
264e5c59547SJaswinder Singh Rajput 	} else {
265e5c59547SJaswinder Singh Rajput 		sprintf(name, "%s-%s", hw_cache[cache_type][0],
266e5c59547SJaswinder Singh Rajput 			hw_cache_op[cache_op][1]);
267e5c59547SJaswinder Singh Rajput 	}
268e5c59547SJaswinder Singh Rajput 
269e5c59547SJaswinder Singh Rajput 	return name;
270e5c59547SJaswinder Singh Rajput }
271e5c59547SJaswinder Singh Rajput 
27283a0944fSIngo Molnar const char *event_name(int counter)
27386470930SIngo Molnar {
2749cffa8d5SPaul Mackerras 	u64 config = attrs[counter].config;
27586470930SIngo Molnar 	int type = attrs[counter].type;
2768f18aec5SPeter Zijlstra 
2778f18aec5SPeter Zijlstra 	return __event_name(type, config);
2788f18aec5SPeter Zijlstra }
2798f18aec5SPeter Zijlstra 
28083a0944fSIngo Molnar const char *__event_name(int type, u64 config)
2818f18aec5SPeter Zijlstra {
28286470930SIngo Molnar 	static char buf[32];
28386470930SIngo Molnar 
2848f18aec5SPeter Zijlstra 	if (type == PERF_TYPE_RAW) {
28586470930SIngo Molnar 		sprintf(buf, "raw 0x%llx", config);
28686470930SIngo Molnar 		return buf;
28786470930SIngo Molnar 	}
28886470930SIngo Molnar 
28986470930SIngo Molnar 	switch (type) {
29086470930SIngo Molnar 	case PERF_TYPE_HARDWARE:
291f4dbfa8fSPeter Zijlstra 		if (config < PERF_COUNT_HW_MAX)
29286470930SIngo Molnar 			return hw_event_names[config];
29386470930SIngo Molnar 		return "unknown-hardware";
29486470930SIngo Molnar 
29586470930SIngo Molnar 	case PERF_TYPE_HW_CACHE: {
2969cffa8d5SPaul Mackerras 		u8 cache_type, cache_op, cache_result;
29786470930SIngo Molnar 
29886470930SIngo Molnar 		cache_type   = (config >>  0) & 0xff;
29986470930SIngo Molnar 		if (cache_type > PERF_COUNT_HW_CACHE_MAX)
30086470930SIngo Molnar 			return "unknown-ext-hardware-cache-type";
30186470930SIngo Molnar 
30286470930SIngo Molnar 		cache_op     = (config >>  8) & 0xff;
30386470930SIngo Molnar 		if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX)
30486470930SIngo Molnar 			return "unknown-ext-hardware-cache-op";
30586470930SIngo Molnar 
30686470930SIngo Molnar 		cache_result = (config >> 16) & 0xff;
30786470930SIngo Molnar 		if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX)
30886470930SIngo Molnar 			return "unknown-ext-hardware-cache-result";
30986470930SIngo Molnar 
31006813f6cSJaswinder Singh Rajput 		if (!is_cache_op_valid(cache_type, cache_op))
31106813f6cSJaswinder Singh Rajput 			return "invalid-cache";
31286470930SIngo Molnar 
313e5c59547SJaswinder Singh Rajput 		return event_cache_name(cache_type, cache_op, cache_result);
31486470930SIngo Molnar 	}
31586470930SIngo Molnar 
31686470930SIngo Molnar 	case PERF_TYPE_SOFTWARE:
317f4dbfa8fSPeter Zijlstra 		if (config < PERF_COUNT_SW_MAX)
31886470930SIngo Molnar 			return sw_event_names[config];
31986470930SIngo Molnar 		return "unknown-software";
32086470930SIngo Molnar 
321f6bdafefSJason Baron 	case PERF_TYPE_TRACEPOINT:
322f6bdafefSJason Baron 		return tracepoint_id_to_name(config);
323f6bdafefSJason Baron 
32486470930SIngo Molnar 	default:
32586470930SIngo Molnar 		break;
32686470930SIngo Molnar 	}
32786470930SIngo Molnar 
32886470930SIngo Molnar 	return "unknown";
32986470930SIngo Molnar }
33086470930SIngo Molnar 
33183a0944fSIngo Molnar static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int size)
33286470930SIngo Molnar {
33386470930SIngo Molnar 	int i, j;
33461c45981SPaul Mackerras 	int n, longest = -1;
33586470930SIngo Molnar 
33686470930SIngo Molnar 	for (i = 0; i < size; i++) {
33761c45981SPaul Mackerras 		for (j = 0; j < MAX_ALIASES && names[i][j]; j++) {
33861c45981SPaul Mackerras 			n = strlen(names[i][j]);
33961c45981SPaul Mackerras 			if (n > longest && !strncasecmp(*str, names[i][j], n))
34061c45981SPaul Mackerras 				longest = n;
34161c45981SPaul Mackerras 		}
34261c45981SPaul Mackerras 		if (longest > 0) {
34361c45981SPaul Mackerras 			*str += longest;
34486470930SIngo Molnar 			return i;
34586470930SIngo Molnar 		}
34686470930SIngo Molnar 	}
34786470930SIngo Molnar 
3488953645fSIngo Molnar 	return -1;
34986470930SIngo Molnar }
35086470930SIngo Molnar 
351bcd3279fSFrederic Weisbecker static enum event_result
352cdd6c482SIngo Molnar parse_generic_hw_event(const char **str, struct perf_event_attr *attr)
35386470930SIngo Molnar {
35461c45981SPaul Mackerras 	const char *s = *str;
35561c45981SPaul Mackerras 	int cache_type = -1, cache_op = -1, cache_result = -1;
35686470930SIngo Molnar 
35761c45981SPaul Mackerras 	cache_type = parse_aliases(&s, hw_cache, PERF_COUNT_HW_CACHE_MAX);
35886470930SIngo Molnar 	/*
35986470930SIngo Molnar 	 * No fallback - if we cannot get a clear cache type
36086470930SIngo Molnar 	 * then bail out:
36186470930SIngo Molnar 	 */
36286470930SIngo Molnar 	if (cache_type == -1)
363bcd3279fSFrederic Weisbecker 		return EVT_FAILED;
36486470930SIngo Molnar 
36561c45981SPaul Mackerras 	while ((cache_op == -1 || cache_result == -1) && *s == '-') {
36661c45981SPaul Mackerras 		++s;
36761c45981SPaul Mackerras 
36861c45981SPaul Mackerras 		if (cache_op == -1) {
36961c45981SPaul Mackerras 			cache_op = parse_aliases(&s, hw_cache_op,
37061c45981SPaul Mackerras 						PERF_COUNT_HW_CACHE_OP_MAX);
37161c45981SPaul Mackerras 			if (cache_op >= 0) {
37261c45981SPaul Mackerras 				if (!is_cache_op_valid(cache_type, cache_op))
37361c45981SPaul Mackerras 					return 0;
37461c45981SPaul Mackerras 				continue;
37561c45981SPaul Mackerras 			}
37661c45981SPaul Mackerras 		}
37761c45981SPaul Mackerras 
37861c45981SPaul Mackerras 		if (cache_result == -1) {
37961c45981SPaul Mackerras 			cache_result = parse_aliases(&s, hw_cache_result,
38061c45981SPaul Mackerras 						PERF_COUNT_HW_CACHE_RESULT_MAX);
38161c45981SPaul Mackerras 			if (cache_result >= 0)
38261c45981SPaul Mackerras 				continue;
38361c45981SPaul Mackerras 		}
38461c45981SPaul Mackerras 
38561c45981SPaul Mackerras 		/*
38661c45981SPaul Mackerras 		 * Can't parse this as a cache op or result, so back up
38761c45981SPaul Mackerras 		 * to the '-'.
38861c45981SPaul Mackerras 		 */
38961c45981SPaul Mackerras 		--s;
39061c45981SPaul Mackerras 		break;
39161c45981SPaul Mackerras 	}
39261c45981SPaul Mackerras 
39386470930SIngo Molnar 	/*
39486470930SIngo Molnar 	 * Fall back to reads:
39586470930SIngo Molnar 	 */
3968953645fSIngo Molnar 	if (cache_op == -1)
3978953645fSIngo Molnar 		cache_op = PERF_COUNT_HW_CACHE_OP_READ;
39886470930SIngo Molnar 
39986470930SIngo Molnar 	/*
40086470930SIngo Molnar 	 * Fall back to accesses:
40186470930SIngo Molnar 	 */
40286470930SIngo Molnar 	if (cache_result == -1)
40386470930SIngo Molnar 		cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS;
40486470930SIngo Molnar 
40586470930SIngo Molnar 	attr->config = cache_type | (cache_op << 8) | (cache_result << 16);
40686470930SIngo Molnar 	attr->type = PERF_TYPE_HW_CACHE;
40786470930SIngo Molnar 
40861c45981SPaul Mackerras 	*str = s;
409bcd3279fSFrederic Weisbecker 	return EVT_HANDLED;
41086470930SIngo Molnar }
41186470930SIngo Molnar 
412bcd3279fSFrederic Weisbecker static enum event_result
413bcd3279fSFrederic Weisbecker parse_single_tracepoint_event(char *sys_name,
414bcd3279fSFrederic Weisbecker 			      const char *evt_name,
415bcd3279fSFrederic Weisbecker 			      unsigned int evt_length,
416bcd3279fSFrederic Weisbecker 			      char *flags,
417cdd6c482SIngo Molnar 			      struct perf_event_attr *attr,
418bcd3279fSFrederic Weisbecker 			      const char **strp)
419bcd3279fSFrederic Weisbecker {
420bcd3279fSFrederic Weisbecker 	char evt_path[MAXPATHLEN];
421bcd3279fSFrederic Weisbecker 	char id_buf[4];
422bcd3279fSFrederic Weisbecker 	u64 id;
423bcd3279fSFrederic Weisbecker 	int fd;
424bcd3279fSFrederic Weisbecker 
425bcd3279fSFrederic Weisbecker 	if (flags) {
4261281a49bSLi Zefan 		if (!strncmp(flags, "record", strlen(flags))) {
427bcd3279fSFrederic Weisbecker 			attr->sample_type |= PERF_SAMPLE_RAW;
4281281a49bSLi Zefan 			attr->sample_type |= PERF_SAMPLE_TIME;
4291281a49bSLi Zefan 			attr->sample_type |= PERF_SAMPLE_CPU;
4301281a49bSLi Zefan 		}
431bcd3279fSFrederic Weisbecker 	}
432bcd3279fSFrederic Weisbecker 
433bcd3279fSFrederic Weisbecker 	snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
434bcd3279fSFrederic Weisbecker 		 sys_name, evt_name);
435bcd3279fSFrederic Weisbecker 
436bcd3279fSFrederic Weisbecker 	fd = open(evt_path, O_RDONLY);
437bcd3279fSFrederic Weisbecker 	if (fd < 0)
438bcd3279fSFrederic Weisbecker 		return EVT_FAILED;
439bcd3279fSFrederic Weisbecker 
440bcd3279fSFrederic Weisbecker 	if (read(fd, id_buf, sizeof(id_buf)) < 0) {
441bcd3279fSFrederic Weisbecker 		close(fd);
442bcd3279fSFrederic Weisbecker 		return EVT_FAILED;
443bcd3279fSFrederic Weisbecker 	}
444bcd3279fSFrederic Weisbecker 
445bcd3279fSFrederic Weisbecker 	close(fd);
446bcd3279fSFrederic Weisbecker 	id = atoll(id_buf);
447bcd3279fSFrederic Weisbecker 	attr->config = id;
448bcd3279fSFrederic Weisbecker 	attr->type = PERF_TYPE_TRACEPOINT;
449bcd3279fSFrederic Weisbecker 	*strp = evt_name + evt_length;
450bcd3279fSFrederic Weisbecker 
451bcd3279fSFrederic Weisbecker 	return EVT_HANDLED;
452bcd3279fSFrederic Weisbecker }
453bcd3279fSFrederic Weisbecker 
454bcd3279fSFrederic Weisbecker /* sys + ':' + event + ':' + flags*/
455bcd3279fSFrederic Weisbecker #define MAX_EVOPT_LEN	(MAX_EVENT_LENGTH * 2 + 2 + 128)
456bcd3279fSFrederic Weisbecker static enum event_result
457bcd3279fSFrederic Weisbecker parse_subsystem_tracepoint_event(char *sys_name, char *flags)
458bcd3279fSFrederic Weisbecker {
459bcd3279fSFrederic Weisbecker 	char evt_path[MAXPATHLEN];
460bcd3279fSFrederic Weisbecker 	struct dirent *evt_ent;
461bcd3279fSFrederic Weisbecker 	DIR *evt_dir;
462bcd3279fSFrederic Weisbecker 
463bcd3279fSFrederic Weisbecker 	snprintf(evt_path, MAXPATHLEN, "%s/%s", debugfs_path, sys_name);
464bcd3279fSFrederic Weisbecker 	evt_dir = opendir(evt_path);
465bcd3279fSFrederic Weisbecker 
466bcd3279fSFrederic Weisbecker 	if (!evt_dir) {
467bcd3279fSFrederic Weisbecker 		perror("Can't open event dir");
468bcd3279fSFrederic Weisbecker 		return EVT_FAILED;
469bcd3279fSFrederic Weisbecker 	}
470bcd3279fSFrederic Weisbecker 
471bcd3279fSFrederic Weisbecker 	while ((evt_ent = readdir(evt_dir))) {
472bcd3279fSFrederic Weisbecker 		char event_opt[MAX_EVOPT_LEN + 1];
473bcd3279fSFrederic Weisbecker 		int len;
474bcd3279fSFrederic Weisbecker 		unsigned int rem = MAX_EVOPT_LEN;
475bcd3279fSFrederic Weisbecker 
476bcd3279fSFrederic Weisbecker 		if (!strcmp(evt_ent->d_name, ".")
477bcd3279fSFrederic Weisbecker 		    || !strcmp(evt_ent->d_name, "..")
478bcd3279fSFrederic Weisbecker 		    || !strcmp(evt_ent->d_name, "enable")
479bcd3279fSFrederic Weisbecker 		    || !strcmp(evt_ent->d_name, "filter"))
480bcd3279fSFrederic Weisbecker 			continue;
481bcd3279fSFrederic Weisbecker 
482bcd3279fSFrederic Weisbecker 		len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s", sys_name,
483bcd3279fSFrederic Weisbecker 			       evt_ent->d_name);
484bcd3279fSFrederic Weisbecker 		if (len < 0)
485bcd3279fSFrederic Weisbecker 			return EVT_FAILED;
486bcd3279fSFrederic Weisbecker 
487bcd3279fSFrederic Weisbecker 		rem -= len;
488bcd3279fSFrederic Weisbecker 		if (flags) {
489bcd3279fSFrederic Weisbecker 			if (rem < strlen(flags) + 1)
490bcd3279fSFrederic Weisbecker 				return EVT_FAILED;
491bcd3279fSFrederic Weisbecker 
492bcd3279fSFrederic Weisbecker 			strcat(event_opt, ":");
493bcd3279fSFrederic Weisbecker 			strcat(event_opt, flags);
494bcd3279fSFrederic Weisbecker 		}
495bcd3279fSFrederic Weisbecker 
496bcd3279fSFrederic Weisbecker 		if (parse_events(NULL, event_opt, 0))
497bcd3279fSFrederic Weisbecker 			return EVT_FAILED;
498bcd3279fSFrederic Weisbecker 	}
499bcd3279fSFrederic Weisbecker 
500bcd3279fSFrederic Weisbecker 	return EVT_HANDLED_ALL;
501bcd3279fSFrederic Weisbecker }
502bcd3279fSFrederic Weisbecker 
503bcd3279fSFrederic Weisbecker 
504bcd3279fSFrederic Weisbecker static enum event_result parse_tracepoint_event(const char **strp,
505cdd6c482SIngo Molnar 				    struct perf_event_attr *attr)
506f6bdafefSJason Baron {
507f6bdafefSJason Baron 	const char *evt_name;
5083a9f131fSFrederic Weisbecker 	char *flags;
509f6bdafefSJason Baron 	char sys_name[MAX_EVENT_LENGTH];
510f6bdafefSJason Baron 	unsigned int sys_length, evt_length;
511f6bdafefSJason Baron 
5125beeded1SJason Baron 	if (valid_debugfs_mount(debugfs_path))
513f6bdafefSJason Baron 		return 0;
514f6bdafefSJason Baron 
515f6bdafefSJason Baron 	evt_name = strchr(*strp, ':');
516f6bdafefSJason Baron 	if (!evt_name)
517bcd3279fSFrederic Weisbecker 		return EVT_FAILED;
518f6bdafefSJason Baron 
519f6bdafefSJason Baron 	sys_length = evt_name - *strp;
520f6bdafefSJason Baron 	if (sys_length >= MAX_EVENT_LENGTH)
521f6bdafefSJason Baron 		return 0;
522f6bdafefSJason Baron 
523f6bdafefSJason Baron 	strncpy(sys_name, *strp, sys_length);
524f6bdafefSJason Baron 	sys_name[sys_length] = '\0';
525f6bdafefSJason Baron 	evt_name = evt_name + 1;
5263a9f131fSFrederic Weisbecker 
5273a9f131fSFrederic Weisbecker 	flags = strchr(evt_name, ':');
5283a9f131fSFrederic Weisbecker 	if (flags) {
5291fc35b29SIngo Molnar 		/* split it out: */
5301fc35b29SIngo Molnar 		evt_name = strndup(evt_name, flags - evt_name);
5313a9f131fSFrederic Weisbecker 		flags++;
5323a9f131fSFrederic Weisbecker 	}
5333a9f131fSFrederic Weisbecker 
534f6bdafefSJason Baron 	evt_length = strlen(evt_name);
535f6bdafefSJason Baron 	if (evt_length >= MAX_EVENT_LENGTH)
536bcd3279fSFrederic Weisbecker 		return EVT_FAILED;
537f6bdafefSJason Baron 
538bcd3279fSFrederic Weisbecker 	if (!strcmp(evt_name, "*")) {
539f6bdafefSJason Baron 		*strp = evt_name + evt_length;
540bcd3279fSFrederic Weisbecker 		return parse_subsystem_tracepoint_event(sys_name, flags);
541bcd3279fSFrederic Weisbecker 	} else
542bcd3279fSFrederic Weisbecker 		return parse_single_tracepoint_event(sys_name, evt_name,
543bcd3279fSFrederic Weisbecker 						     evt_length, flags,
544bcd3279fSFrederic Weisbecker 						     attr, strp);
545f6bdafefSJason Baron }
546f6bdafefSJason Baron 
54774d5b588SJaswinder Singh Rajput static int check_events(const char *str, unsigned int i)
54874d5b588SJaswinder Singh Rajput {
54961c45981SPaul Mackerras 	int n;
55074d5b588SJaswinder Singh Rajput 
55161c45981SPaul Mackerras 	n = strlen(event_symbols[i].symbol);
55261c45981SPaul Mackerras 	if (!strncmp(str, event_symbols[i].symbol, n))
55361c45981SPaul Mackerras 		return n;
55461c45981SPaul Mackerras 
55561c45981SPaul Mackerras 	n = strlen(event_symbols[i].alias);
55661c45981SPaul Mackerras 	if (n)
55761c45981SPaul Mackerras 		if (!strncmp(str, event_symbols[i].alias, n))
55861c45981SPaul Mackerras 			return n;
55961c45981SPaul Mackerras 	return 0;
56061c45981SPaul Mackerras }
56161c45981SPaul Mackerras 
562bcd3279fSFrederic Weisbecker static enum event_result
563cdd6c482SIngo Molnar parse_symbolic_event(const char **strp, struct perf_event_attr *attr)
56461c45981SPaul Mackerras {
56561c45981SPaul Mackerras 	const char *str = *strp;
56661c45981SPaul Mackerras 	unsigned int i;
56761c45981SPaul Mackerras 	int n;
56861c45981SPaul Mackerras 
56961c45981SPaul Mackerras 	for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
57061c45981SPaul Mackerras 		n = check_events(str, i);
57161c45981SPaul Mackerras 		if (n > 0) {
57261c45981SPaul Mackerras 			attr->type = event_symbols[i].type;
57361c45981SPaul Mackerras 			attr->config = event_symbols[i].config;
57461c45981SPaul Mackerras 			*strp = str + n;
575bcd3279fSFrederic Weisbecker 			return EVT_HANDLED;
57661c45981SPaul Mackerras 		}
57761c45981SPaul Mackerras 	}
578bcd3279fSFrederic Weisbecker 	return EVT_FAILED;
57961c45981SPaul Mackerras }
58061c45981SPaul Mackerras 
581bcd3279fSFrederic Weisbecker static enum event_result
582cdd6c482SIngo Molnar parse_raw_event(const char **strp, struct perf_event_attr *attr)
58361c45981SPaul Mackerras {
58461c45981SPaul Mackerras 	const char *str = *strp;
58561c45981SPaul Mackerras 	u64 config;
58661c45981SPaul Mackerras 	int n;
58761c45981SPaul Mackerras 
58861c45981SPaul Mackerras 	if (*str != 'r')
589bcd3279fSFrederic Weisbecker 		return EVT_FAILED;
59061c45981SPaul Mackerras 	n = hex2u64(str + 1, &config);
59161c45981SPaul Mackerras 	if (n > 0) {
59261c45981SPaul Mackerras 		*strp = str + n + 1;
59361c45981SPaul Mackerras 		attr->type = PERF_TYPE_RAW;
59461c45981SPaul Mackerras 		attr->config = config;
595bcd3279fSFrederic Weisbecker 		return EVT_HANDLED;
59661c45981SPaul Mackerras 	}
597bcd3279fSFrederic Weisbecker 	return EVT_FAILED;
59861c45981SPaul Mackerras }
59961c45981SPaul Mackerras 
600bcd3279fSFrederic Weisbecker static enum event_result
601cdd6c482SIngo Molnar parse_numeric_event(const char **strp, struct perf_event_attr *attr)
60261c45981SPaul Mackerras {
60361c45981SPaul Mackerras 	const char *str = *strp;
60461c45981SPaul Mackerras 	char *endp;
60561c45981SPaul Mackerras 	unsigned long type;
60661c45981SPaul Mackerras 	u64 config;
60761c45981SPaul Mackerras 
60861c45981SPaul Mackerras 	type = strtoul(str, &endp, 0);
60961c45981SPaul Mackerras 	if (endp > str && type < PERF_TYPE_MAX && *endp == ':') {
61061c45981SPaul Mackerras 		str = endp + 1;
61161c45981SPaul Mackerras 		config = strtoul(str, &endp, 0);
61261c45981SPaul Mackerras 		if (endp > str) {
61361c45981SPaul Mackerras 			attr->type = type;
61461c45981SPaul Mackerras 			attr->config = config;
61561c45981SPaul Mackerras 			*strp = endp;
616bcd3279fSFrederic Weisbecker 			return EVT_HANDLED;
61761c45981SPaul Mackerras 		}
61861c45981SPaul Mackerras 	}
619bcd3279fSFrederic Weisbecker 	return EVT_FAILED;
62061c45981SPaul Mackerras }
62161c45981SPaul Mackerras 
622bcd3279fSFrederic Weisbecker static enum event_result
623cdd6c482SIngo Molnar parse_event_modifier(const char **strp, struct perf_event_attr *attr)
62461c45981SPaul Mackerras {
62561c45981SPaul Mackerras 	const char *str = *strp;
62661c45981SPaul Mackerras 	int eu = 1, ek = 1, eh = 1;
62761c45981SPaul Mackerras 
62861c45981SPaul Mackerras 	if (*str++ != ':')
62961c45981SPaul Mackerras 		return 0;
63061c45981SPaul Mackerras 	while (*str) {
63161c45981SPaul Mackerras 		if (*str == 'u')
63261c45981SPaul Mackerras 			eu = 0;
63361c45981SPaul Mackerras 		else if (*str == 'k')
63461c45981SPaul Mackerras 			ek = 0;
63561c45981SPaul Mackerras 		else if (*str == 'h')
63661c45981SPaul Mackerras 			eh = 0;
63761c45981SPaul Mackerras 		else
63861c45981SPaul Mackerras 			break;
63961c45981SPaul Mackerras 		++str;
64061c45981SPaul Mackerras 	}
64161c45981SPaul Mackerras 	if (str >= *strp + 2) {
64261c45981SPaul Mackerras 		*strp = str;
64361c45981SPaul Mackerras 		attr->exclude_user   = eu;
64461c45981SPaul Mackerras 		attr->exclude_kernel = ek;
64561c45981SPaul Mackerras 		attr->exclude_hv     = eh;
64661c45981SPaul Mackerras 		return 1;
64761c45981SPaul Mackerras 	}
64874d5b588SJaswinder Singh Rajput 	return 0;
64974d5b588SJaswinder Singh Rajput }
65074d5b588SJaswinder Singh Rajput 
65186470930SIngo Molnar /*
65286470930SIngo Molnar  * Each event can have multiple symbolic names.
65386470930SIngo Molnar  * Symbolic names are (almost) exactly matched.
65486470930SIngo Molnar  */
655bcd3279fSFrederic Weisbecker static enum event_result
656cdd6c482SIngo Molnar parse_event_symbols(const char **str, struct perf_event_attr *attr)
65786470930SIngo Molnar {
658bcd3279fSFrederic Weisbecker 	enum event_result ret;
65986470930SIngo Molnar 
660bcd3279fSFrederic Weisbecker 	ret = parse_tracepoint_event(str, attr);
661bcd3279fSFrederic Weisbecker 	if (ret != EVT_FAILED)
662bcd3279fSFrederic Weisbecker 		goto modifier;
663bcd3279fSFrederic Weisbecker 
664bcd3279fSFrederic Weisbecker 	ret = parse_raw_event(str, attr);
665bcd3279fSFrederic Weisbecker 	if (ret != EVT_FAILED)
666bcd3279fSFrederic Weisbecker 		goto modifier;
667bcd3279fSFrederic Weisbecker 
668bcd3279fSFrederic Weisbecker 	ret = parse_numeric_event(str, attr);
669bcd3279fSFrederic Weisbecker 	if (ret != EVT_FAILED)
670bcd3279fSFrederic Weisbecker 		goto modifier;
671bcd3279fSFrederic Weisbecker 
672bcd3279fSFrederic Weisbecker 	ret = parse_symbolic_event(str, attr);
673bcd3279fSFrederic Weisbecker 	if (ret != EVT_FAILED)
674bcd3279fSFrederic Weisbecker 		goto modifier;
675bcd3279fSFrederic Weisbecker 
676bcd3279fSFrederic Weisbecker 	ret = parse_generic_hw_event(str, attr);
677bcd3279fSFrederic Weisbecker 	if (ret != EVT_FAILED)
678bcd3279fSFrederic Weisbecker 		goto modifier;
679bcd3279fSFrederic Weisbecker 
680bcd3279fSFrederic Weisbecker 	return EVT_FAILED;
681bcd3279fSFrederic Weisbecker 
682bcd3279fSFrederic Weisbecker modifier:
68361c45981SPaul Mackerras 	parse_event_modifier(str, attr);
68486470930SIngo Molnar 
685bcd3279fSFrederic Weisbecker 	return ret;
68686470930SIngo Molnar }
68786470930SIngo Molnar 
6888755a8f2SArjan van de Ven static void store_event_type(const char *orgname)
6898755a8f2SArjan van de Ven {
6908755a8f2SArjan van de Ven 	char filename[PATH_MAX], *c;
6918755a8f2SArjan van de Ven 	FILE *file;
6928755a8f2SArjan van de Ven 	int id;
6938755a8f2SArjan van de Ven 
694*63c9e01eSAshwin Chaugule 	sprintf(filename, "%s/", debugfs_path);
695*63c9e01eSAshwin Chaugule 	strncat(filename, orgname, strlen(orgname));
696*63c9e01eSAshwin Chaugule 	strcat(filename, "/id");
697*63c9e01eSAshwin Chaugule 
6988755a8f2SArjan van de Ven 	c = strchr(filename, ':');
6998755a8f2SArjan van de Ven 	if (c)
7008755a8f2SArjan van de Ven 		*c = '/';
7018755a8f2SArjan van de Ven 
7028755a8f2SArjan van de Ven 	file = fopen(filename, "r");
7038755a8f2SArjan van de Ven 	if (!file)
7048755a8f2SArjan van de Ven 		return;
7058755a8f2SArjan van de Ven 	if (fscanf(file, "%i", &id) < 1)
7068755a8f2SArjan van de Ven 		die("cannot store event ID");
7078755a8f2SArjan van de Ven 	fclose(file);
7088755a8f2SArjan van de Ven 	perf_header__push_event(id, orgname);
7098755a8f2SArjan van de Ven }
7108755a8f2SArjan van de Ven 
7118755a8f2SArjan van de Ven 
712f37a291cSIngo Molnar int parse_events(const struct option *opt __used, const char *str, int unset __used)
71386470930SIngo Molnar {
714cdd6c482SIngo Molnar 	struct perf_event_attr attr;
715bcd3279fSFrederic Weisbecker 	enum event_result ret;
71686470930SIngo Molnar 
7178755a8f2SArjan van de Ven 	if (strchr(str, ':'))
7188755a8f2SArjan van de Ven 		store_event_type(str);
7198755a8f2SArjan van de Ven 
72061c45981SPaul Mackerras 	for (;;) {
72186470930SIngo Molnar 		if (nr_counters == MAX_COUNTERS)
72286470930SIngo Molnar 			return -1;
72386470930SIngo Molnar 
72461c45981SPaul Mackerras 		memset(&attr, 0, sizeof(attr));
725bcd3279fSFrederic Weisbecker 		ret = parse_event_symbols(&str, &attr);
726bcd3279fSFrederic Weisbecker 		if (ret == EVT_FAILED)
72761c45981SPaul Mackerras 			return -1;
72861c45981SPaul Mackerras 
72961c45981SPaul Mackerras 		if (!(*str == 0 || *str == ',' || isspace(*str)))
73061c45981SPaul Mackerras 			return -1;
73186470930SIngo Molnar 
732bcd3279fSFrederic Weisbecker 		if (ret != EVT_HANDLED_ALL) {
73386470930SIngo Molnar 			attrs[nr_counters] = attr;
73486470930SIngo Molnar 			nr_counters++;
735bcd3279fSFrederic Weisbecker 		}
73686470930SIngo Molnar 
73761c45981SPaul Mackerras 		if (*str == 0)
73861c45981SPaul Mackerras 			break;
73961c45981SPaul Mackerras 		if (*str == ',')
74061c45981SPaul Mackerras 			++str;
74161c45981SPaul Mackerras 		while (isspace(*str))
74261c45981SPaul Mackerras 			++str;
74386470930SIngo Molnar 	}
74486470930SIngo Molnar 
74586470930SIngo Molnar 	return 0;
74686470930SIngo Molnar }
74786470930SIngo Molnar 
74886470930SIngo Molnar static const char * const event_type_descriptors[] = {
74986470930SIngo Molnar 	"",
75086470930SIngo Molnar 	"Hardware event",
75186470930SIngo Molnar 	"Software event",
75286470930SIngo Molnar 	"Tracepoint event",
75386470930SIngo Molnar 	"Hardware cache event",
75486470930SIngo Molnar };
75586470930SIngo Molnar 
75686470930SIngo Molnar /*
757f6bdafefSJason Baron  * Print the events from <debugfs_mount_point>/tracing/events
758f6bdafefSJason Baron  */
759f6bdafefSJason Baron 
760f6bdafefSJason Baron static void print_tracepoint_events(void)
761f6bdafefSJason Baron {
762f6bdafefSJason Baron 	DIR *sys_dir, *evt_dir;
763f6bdafefSJason Baron 	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
764f6bdafefSJason Baron 	char evt_path[MAXPATHLEN];
765725b1368SEric Dumazet 	char dir_path[MAXPATHLEN];
766f6bdafefSJason Baron 
7675beeded1SJason Baron 	if (valid_debugfs_mount(debugfs_path))
768f6bdafefSJason Baron 		return;
769f6bdafefSJason Baron 
7705beeded1SJason Baron 	sys_dir = opendir(debugfs_path);
771f6bdafefSJason Baron 	if (!sys_dir)
772725b1368SEric Dumazet 		return;
773f6bdafefSJason Baron 
7746b58e7f1SUlrich Drepper 	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
775725b1368SEric Dumazet 
776725b1368SEric Dumazet 		snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
777725b1368SEric Dumazet 			 sys_dirent.d_name);
778725b1368SEric Dumazet 		evt_dir = opendir(dir_path);
779725b1368SEric Dumazet 		if (!evt_dir)
7806b58e7f1SUlrich Drepper 			continue;
781725b1368SEric Dumazet 
7826b58e7f1SUlrich Drepper 		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
783f6bdafefSJason Baron 			snprintf(evt_path, MAXPATHLEN, "%s:%s",
784f6bdafefSJason Baron 				 sys_dirent.d_name, evt_dirent.d_name);
78548c2e17fSJason Baron 			fprintf(stderr, "  %-42s [%s]\n", evt_path,
786f6bdafefSJason Baron 				event_type_descriptors[PERF_TYPE_TRACEPOINT+1]);
787f6bdafefSJason Baron 		}
788f6bdafefSJason Baron 		closedir(evt_dir);
789f6bdafefSJason Baron 	}
790f6bdafefSJason Baron 	closedir(sys_dir);
791f6bdafefSJason Baron }
792f6bdafefSJason Baron 
793f6bdafefSJason Baron /*
79486470930SIngo Molnar  * Print the help text for the event symbols:
79586470930SIngo Molnar  */
79686470930SIngo Molnar void print_events(void)
79786470930SIngo Molnar {
79886470930SIngo Molnar 	struct event_symbol *syms = event_symbols;
79973c24cb8SJaswinder Singh Rajput 	unsigned int i, type, op, prev_type = -1;
80074d5b588SJaswinder Singh Rajput 	char name[40];
80186470930SIngo Molnar 
80286470930SIngo Molnar 	fprintf(stderr, "\n");
80386470930SIngo Molnar 	fprintf(stderr, "List of pre-defined events (to be used in -e):\n");
80486470930SIngo Molnar 
80586470930SIngo Molnar 	for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
80686470930SIngo Molnar 		type = syms->type + 1;
80723cdb5d5SRoel Kluin 		if (type >= ARRAY_SIZE(event_type_descriptors))
80886470930SIngo Molnar 			type = 0;
80986470930SIngo Molnar 
81086470930SIngo Molnar 		if (type != prev_type)
81186470930SIngo Molnar 			fprintf(stderr, "\n");
81286470930SIngo Molnar 
81374d5b588SJaswinder Singh Rajput 		if (strlen(syms->alias))
81474d5b588SJaswinder Singh Rajput 			sprintf(name, "%s OR %s", syms->symbol, syms->alias);
81574d5b588SJaswinder Singh Rajput 		else
81674d5b588SJaswinder Singh Rajput 			strcpy(name, syms->symbol);
81748c2e17fSJason Baron 		fprintf(stderr, "  %-42s [%s]\n", name,
81886470930SIngo Molnar 			event_type_descriptors[type]);
81986470930SIngo Molnar 
82086470930SIngo Molnar 		prev_type = type;
82186470930SIngo Molnar 	}
82286470930SIngo Molnar 
82386470930SIngo Molnar 	fprintf(stderr, "\n");
82473c24cb8SJaswinder Singh Rajput 	for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
82573c24cb8SJaswinder Singh Rajput 		for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
82673c24cb8SJaswinder Singh Rajput 			/* skip invalid cache type */
82773c24cb8SJaswinder Singh Rajput 			if (!is_cache_op_valid(type, op))
82873c24cb8SJaswinder Singh Rajput 				continue;
82973c24cb8SJaswinder Singh Rajput 
83073c24cb8SJaswinder Singh Rajput 			for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
83148c2e17fSJason Baron 				fprintf(stderr, "  %-42s [%s]\n",
83273c24cb8SJaswinder Singh Rajput 					event_cache_name(type, op, i),
83373c24cb8SJaswinder Singh Rajput 					event_type_descriptors[4]);
83473c24cb8SJaswinder Singh Rajput 			}
83573c24cb8SJaswinder Singh Rajput 		}
83673c24cb8SJaswinder Singh Rajput 	}
83773c24cb8SJaswinder Singh Rajput 
83873c24cb8SJaswinder Singh Rajput 	fprintf(stderr, "\n");
83948c2e17fSJason Baron 	fprintf(stderr, "  %-42s [raw hardware event descriptor]\n",
84086470930SIngo Molnar 		"rNNN");
84186470930SIngo Molnar 	fprintf(stderr, "\n");
84286470930SIngo Molnar 
843f6bdafefSJason Baron 	print_tracepoint_events();
844f6bdafefSJason Baron 
84586470930SIngo Molnar 	exit(129);
84686470930SIngo Molnar }
847