xref: /linux/tools/perf/util/parse-events.c (revision cdd6c482c9ff9c55475ee7392ec8f672eddb7be6)
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 
13*cdd6c482SIngo 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 
51*cdd6c482SIngo Molnar #define __PERF_EVENT_FIELD(config, name) \
52*cdd6c482SIngo Molnar 	((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT)
5386470930SIngo Molnar 
54*cdd6c482SIngo Molnar #define PERF_EVENT_RAW(config)	__PERF_EVENT_FIELD(config, RAW)
55*cdd6c482SIngo Molnar #define PERF_EVENT_CONFIG(config)	__PERF_EVENT_FIELD(config, CONFIG)
56*cdd6c482SIngo Molnar #define PERF_EVENT_TYPE(config)	__PERF_EVENT_FIELD(config, TYPE)
57*cdd6c482SIngo 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];
1686b58e7f1SUlrich Drepper 	int sys_dir_fd, fd;
169f6bdafefSJason Baron 	u64 id;
170f6bdafefSJason Baron 	char evt_path[MAXPATHLEN];
171f6bdafefSJason Baron 
1725beeded1SJason Baron 	if (valid_debugfs_mount(debugfs_path))
1731ef2ed10SFrederic Weisbecker 		return NULL;
174f6bdafefSJason Baron 
1755beeded1SJason Baron 	sys_dir = opendir(debugfs_path);
176f6bdafefSJason Baron 	if (!sys_dir)
177f6bdafefSJason Baron 		goto cleanup;
1786b58e7f1SUlrich Drepper 	sys_dir_fd = dirfd(sys_dir);
179f6bdafefSJason Baron 
1806b58e7f1SUlrich Drepper 	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
1816b58e7f1SUlrich Drepper 		int dfd = openat(sys_dir_fd, sys_dirent.d_name,
1826b58e7f1SUlrich Drepper 				 O_RDONLY|O_DIRECTORY), evt_dir_fd;
1836b58e7f1SUlrich Drepper 		if (dfd == -1)
1846b58e7f1SUlrich Drepper 			continue;
1856b58e7f1SUlrich Drepper 		evt_dir = fdopendir(dfd);
1866b58e7f1SUlrich Drepper 		if (!evt_dir) {
1876b58e7f1SUlrich Drepper 			close(dfd);
1886b58e7f1SUlrich Drepper 			continue;
1896b58e7f1SUlrich Drepper 		}
1906b58e7f1SUlrich Drepper 		evt_dir_fd = dirfd(evt_dir);
1916b58e7f1SUlrich Drepper 		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
1926b58e7f1SUlrich Drepper 			snprintf(evt_path, MAXPATHLEN, "%s/id",
193f6bdafefSJason Baron 				 evt_dirent.d_name);
1946b58e7f1SUlrich Drepper 			fd = openat(evt_dir_fd, evt_path, O_RDONLY);
195f6bdafefSJason Baron 			if (fd < 0)
196f6bdafefSJason Baron 				continue;
197f6bdafefSJason Baron 			if (read(fd, id_buf, sizeof(id_buf)) < 0) {
198f6bdafefSJason Baron 				close(fd);
199f6bdafefSJason Baron 				continue;
200f6bdafefSJason Baron 			}
201f6bdafefSJason Baron 			close(fd);
202f6bdafefSJason Baron 			id = atoll(id_buf);
203f6bdafefSJason Baron 			if (id == config) {
204f6bdafefSJason Baron 				closedir(evt_dir);
205f6bdafefSJason Baron 				closedir(sys_dir);
2061ef2ed10SFrederic Weisbecker 				path = calloc(1, sizeof(path));
2071ef2ed10SFrederic Weisbecker 				path->system = malloc(MAX_EVENT_LENGTH);
2081ef2ed10SFrederic Weisbecker 				if (!path->system) {
2091ef2ed10SFrederic Weisbecker 					free(path);
2101ef2ed10SFrederic Weisbecker 					return NULL;
2111ef2ed10SFrederic Weisbecker 				}
2121ef2ed10SFrederic Weisbecker 				path->name = malloc(MAX_EVENT_LENGTH);
2131ef2ed10SFrederic Weisbecker 				if (!path->name) {
2141ef2ed10SFrederic Weisbecker 					free(path->system);
2151ef2ed10SFrederic Weisbecker 					free(path);
2161ef2ed10SFrederic Weisbecker 					return NULL;
2171ef2ed10SFrederic Weisbecker 				}
2181ef2ed10SFrederic Weisbecker 				strncpy(path->system, sys_dirent.d_name,
2191ef2ed10SFrederic Weisbecker 					MAX_EVENT_LENGTH);
2201ef2ed10SFrederic Weisbecker 				strncpy(path->name, evt_dirent.d_name,
2211ef2ed10SFrederic Weisbecker 					MAX_EVENT_LENGTH);
2221ef2ed10SFrederic Weisbecker 				return path;
223f6bdafefSJason Baron 			}
224f6bdafefSJason Baron 		}
225f6bdafefSJason Baron 		closedir(evt_dir);
226f6bdafefSJason Baron 	}
227f6bdafefSJason Baron 
228f6bdafefSJason Baron cleanup:
229f6bdafefSJason Baron 	closedir(sys_dir);
2301ef2ed10SFrederic Weisbecker 	return NULL;
2311ef2ed10SFrederic Weisbecker }
2321ef2ed10SFrederic Weisbecker 
2331ef2ed10SFrederic Weisbecker #define TP_PATH_LEN (MAX_EVENT_LENGTH * 2 + 1)
2341ef2ed10SFrederic Weisbecker static const char *tracepoint_id_to_name(u64 config)
2351ef2ed10SFrederic Weisbecker {
2361ef2ed10SFrederic Weisbecker 	static char buf[TP_PATH_LEN];
2371ef2ed10SFrederic Weisbecker 	struct tracepoint_path *path;
2381ef2ed10SFrederic Weisbecker 
2391ef2ed10SFrederic Weisbecker 	path = tracepoint_id_to_path(config);
2401ef2ed10SFrederic Weisbecker 	if (path) {
2411ef2ed10SFrederic Weisbecker 		snprintf(buf, TP_PATH_LEN, "%s:%s", path->system, path->name);
2421ef2ed10SFrederic Weisbecker 		free(path->name);
2431ef2ed10SFrederic Weisbecker 		free(path->system);
2441ef2ed10SFrederic Weisbecker 		free(path);
2451ef2ed10SFrederic Weisbecker 	} else
2461ef2ed10SFrederic Weisbecker 		snprintf(buf, TP_PATH_LEN, "%s:%s", "unknown", "unknown");
2471ef2ed10SFrederic Weisbecker 
2481ef2ed10SFrederic Weisbecker 	return buf;
249f6bdafefSJason Baron }
250f6bdafefSJason Baron 
25106813f6cSJaswinder Singh Rajput static int is_cache_op_valid(u8 cache_type, u8 cache_op)
25206813f6cSJaswinder Singh Rajput {
25306813f6cSJaswinder Singh Rajput 	if (hw_cache_stat[cache_type] & COP(cache_op))
25406813f6cSJaswinder Singh Rajput 		return 1;	/* valid */
25506813f6cSJaswinder Singh Rajput 	else
25606813f6cSJaswinder Singh Rajput 		return 0;	/* invalid */
25706813f6cSJaswinder Singh Rajput }
25806813f6cSJaswinder Singh Rajput 
259e5c59547SJaswinder Singh Rajput static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
260e5c59547SJaswinder Singh Rajput {
261e5c59547SJaswinder Singh Rajput 	static char name[50];
262e5c59547SJaswinder Singh Rajput 
263e5c59547SJaswinder Singh Rajput 	if (cache_result) {
264e5c59547SJaswinder Singh Rajput 		sprintf(name, "%s-%s-%s", hw_cache[cache_type][0],
265e5c59547SJaswinder Singh Rajput 			hw_cache_op[cache_op][0],
266e5c59547SJaswinder Singh Rajput 			hw_cache_result[cache_result][0]);
267e5c59547SJaswinder Singh Rajput 	} else {
268e5c59547SJaswinder Singh Rajput 		sprintf(name, "%s-%s", hw_cache[cache_type][0],
269e5c59547SJaswinder Singh Rajput 			hw_cache_op[cache_op][1]);
270e5c59547SJaswinder Singh Rajput 	}
271e5c59547SJaswinder Singh Rajput 
272e5c59547SJaswinder Singh Rajput 	return name;
273e5c59547SJaswinder Singh Rajput }
274e5c59547SJaswinder Singh Rajput 
27583a0944fSIngo Molnar const char *event_name(int counter)
27686470930SIngo Molnar {
2779cffa8d5SPaul Mackerras 	u64 config = attrs[counter].config;
27886470930SIngo Molnar 	int type = attrs[counter].type;
2798f18aec5SPeter Zijlstra 
2808f18aec5SPeter Zijlstra 	return __event_name(type, config);
2818f18aec5SPeter Zijlstra }
2828f18aec5SPeter Zijlstra 
28383a0944fSIngo Molnar const char *__event_name(int type, u64 config)
2848f18aec5SPeter Zijlstra {
28586470930SIngo Molnar 	static char buf[32];
28686470930SIngo Molnar 
2878f18aec5SPeter Zijlstra 	if (type == PERF_TYPE_RAW) {
28886470930SIngo Molnar 		sprintf(buf, "raw 0x%llx", config);
28986470930SIngo Molnar 		return buf;
29086470930SIngo Molnar 	}
29186470930SIngo Molnar 
29286470930SIngo Molnar 	switch (type) {
29386470930SIngo Molnar 	case PERF_TYPE_HARDWARE:
294f4dbfa8fSPeter Zijlstra 		if (config < PERF_COUNT_HW_MAX)
29586470930SIngo Molnar 			return hw_event_names[config];
29686470930SIngo Molnar 		return "unknown-hardware";
29786470930SIngo Molnar 
29886470930SIngo Molnar 	case PERF_TYPE_HW_CACHE: {
2999cffa8d5SPaul Mackerras 		u8 cache_type, cache_op, cache_result;
30086470930SIngo Molnar 
30186470930SIngo Molnar 		cache_type   = (config >>  0) & 0xff;
30286470930SIngo Molnar 		if (cache_type > PERF_COUNT_HW_CACHE_MAX)
30386470930SIngo Molnar 			return "unknown-ext-hardware-cache-type";
30486470930SIngo Molnar 
30586470930SIngo Molnar 		cache_op     = (config >>  8) & 0xff;
30686470930SIngo Molnar 		if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX)
30786470930SIngo Molnar 			return "unknown-ext-hardware-cache-op";
30886470930SIngo Molnar 
30986470930SIngo Molnar 		cache_result = (config >> 16) & 0xff;
31086470930SIngo Molnar 		if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX)
31186470930SIngo Molnar 			return "unknown-ext-hardware-cache-result";
31286470930SIngo Molnar 
31306813f6cSJaswinder Singh Rajput 		if (!is_cache_op_valid(cache_type, cache_op))
31406813f6cSJaswinder Singh Rajput 			return "invalid-cache";
31586470930SIngo Molnar 
316e5c59547SJaswinder Singh Rajput 		return event_cache_name(cache_type, cache_op, cache_result);
31786470930SIngo Molnar 	}
31886470930SIngo Molnar 
31986470930SIngo Molnar 	case PERF_TYPE_SOFTWARE:
320f4dbfa8fSPeter Zijlstra 		if (config < PERF_COUNT_SW_MAX)
32186470930SIngo Molnar 			return sw_event_names[config];
32286470930SIngo Molnar 		return "unknown-software";
32386470930SIngo Molnar 
324f6bdafefSJason Baron 	case PERF_TYPE_TRACEPOINT:
325f6bdafefSJason Baron 		return tracepoint_id_to_name(config);
326f6bdafefSJason Baron 
32786470930SIngo Molnar 	default:
32886470930SIngo Molnar 		break;
32986470930SIngo Molnar 	}
33086470930SIngo Molnar 
33186470930SIngo Molnar 	return "unknown";
33286470930SIngo Molnar }
33386470930SIngo Molnar 
33483a0944fSIngo Molnar static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int size)
33586470930SIngo Molnar {
33686470930SIngo Molnar 	int i, j;
33761c45981SPaul Mackerras 	int n, longest = -1;
33886470930SIngo Molnar 
33986470930SIngo Molnar 	for (i = 0; i < size; i++) {
34061c45981SPaul Mackerras 		for (j = 0; j < MAX_ALIASES && names[i][j]; j++) {
34161c45981SPaul Mackerras 			n = strlen(names[i][j]);
34261c45981SPaul Mackerras 			if (n > longest && !strncasecmp(*str, names[i][j], n))
34361c45981SPaul Mackerras 				longest = n;
34461c45981SPaul Mackerras 		}
34561c45981SPaul Mackerras 		if (longest > 0) {
34661c45981SPaul Mackerras 			*str += longest;
34786470930SIngo Molnar 			return i;
34886470930SIngo Molnar 		}
34986470930SIngo Molnar 	}
35086470930SIngo Molnar 
3518953645fSIngo Molnar 	return -1;
35286470930SIngo Molnar }
35386470930SIngo Molnar 
354bcd3279fSFrederic Weisbecker static enum event_result
355*cdd6c482SIngo Molnar parse_generic_hw_event(const char **str, struct perf_event_attr *attr)
35686470930SIngo Molnar {
35761c45981SPaul Mackerras 	const char *s = *str;
35861c45981SPaul Mackerras 	int cache_type = -1, cache_op = -1, cache_result = -1;
35986470930SIngo Molnar 
36061c45981SPaul Mackerras 	cache_type = parse_aliases(&s, hw_cache, PERF_COUNT_HW_CACHE_MAX);
36186470930SIngo Molnar 	/*
36286470930SIngo Molnar 	 * No fallback - if we cannot get a clear cache type
36386470930SIngo Molnar 	 * then bail out:
36486470930SIngo Molnar 	 */
36586470930SIngo Molnar 	if (cache_type == -1)
366bcd3279fSFrederic Weisbecker 		return EVT_FAILED;
36786470930SIngo Molnar 
36861c45981SPaul Mackerras 	while ((cache_op == -1 || cache_result == -1) && *s == '-') {
36961c45981SPaul Mackerras 		++s;
37061c45981SPaul Mackerras 
37161c45981SPaul Mackerras 		if (cache_op == -1) {
37261c45981SPaul Mackerras 			cache_op = parse_aliases(&s, hw_cache_op,
37361c45981SPaul Mackerras 						PERF_COUNT_HW_CACHE_OP_MAX);
37461c45981SPaul Mackerras 			if (cache_op >= 0) {
37561c45981SPaul Mackerras 				if (!is_cache_op_valid(cache_type, cache_op))
37661c45981SPaul Mackerras 					return 0;
37761c45981SPaul Mackerras 				continue;
37861c45981SPaul Mackerras 			}
37961c45981SPaul Mackerras 		}
38061c45981SPaul Mackerras 
38161c45981SPaul Mackerras 		if (cache_result == -1) {
38261c45981SPaul Mackerras 			cache_result = parse_aliases(&s, hw_cache_result,
38361c45981SPaul Mackerras 						PERF_COUNT_HW_CACHE_RESULT_MAX);
38461c45981SPaul Mackerras 			if (cache_result >= 0)
38561c45981SPaul Mackerras 				continue;
38661c45981SPaul Mackerras 		}
38761c45981SPaul Mackerras 
38861c45981SPaul Mackerras 		/*
38961c45981SPaul Mackerras 		 * Can't parse this as a cache op or result, so back up
39061c45981SPaul Mackerras 		 * to the '-'.
39161c45981SPaul Mackerras 		 */
39261c45981SPaul Mackerras 		--s;
39361c45981SPaul Mackerras 		break;
39461c45981SPaul Mackerras 	}
39561c45981SPaul Mackerras 
39686470930SIngo Molnar 	/*
39786470930SIngo Molnar 	 * Fall back to reads:
39886470930SIngo Molnar 	 */
3998953645fSIngo Molnar 	if (cache_op == -1)
4008953645fSIngo Molnar 		cache_op = PERF_COUNT_HW_CACHE_OP_READ;
40186470930SIngo Molnar 
40286470930SIngo Molnar 	/*
40386470930SIngo Molnar 	 * Fall back to accesses:
40486470930SIngo Molnar 	 */
40586470930SIngo Molnar 	if (cache_result == -1)
40686470930SIngo Molnar 		cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS;
40786470930SIngo Molnar 
40886470930SIngo Molnar 	attr->config = cache_type | (cache_op << 8) | (cache_result << 16);
40986470930SIngo Molnar 	attr->type = PERF_TYPE_HW_CACHE;
41086470930SIngo Molnar 
41161c45981SPaul Mackerras 	*str = s;
412bcd3279fSFrederic Weisbecker 	return EVT_HANDLED;
41386470930SIngo Molnar }
41486470930SIngo Molnar 
415bcd3279fSFrederic Weisbecker static enum event_result
416bcd3279fSFrederic Weisbecker parse_single_tracepoint_event(char *sys_name,
417bcd3279fSFrederic Weisbecker 			      const char *evt_name,
418bcd3279fSFrederic Weisbecker 			      unsigned int evt_length,
419bcd3279fSFrederic Weisbecker 			      char *flags,
420*cdd6c482SIngo Molnar 			      struct perf_event_attr *attr,
421bcd3279fSFrederic Weisbecker 			      const char **strp)
422bcd3279fSFrederic Weisbecker {
423bcd3279fSFrederic Weisbecker 	char evt_path[MAXPATHLEN];
424bcd3279fSFrederic Weisbecker 	char id_buf[4];
425bcd3279fSFrederic Weisbecker 	u64 id;
426bcd3279fSFrederic Weisbecker 	int fd;
427bcd3279fSFrederic Weisbecker 
428bcd3279fSFrederic Weisbecker 	if (flags) {
4291281a49bSLi Zefan 		if (!strncmp(flags, "record", strlen(flags))) {
430bcd3279fSFrederic Weisbecker 			attr->sample_type |= PERF_SAMPLE_RAW;
4311281a49bSLi Zefan 			attr->sample_type |= PERF_SAMPLE_TIME;
4321281a49bSLi Zefan 			attr->sample_type |= PERF_SAMPLE_CPU;
4331281a49bSLi Zefan 		}
434bcd3279fSFrederic Weisbecker 	}
435bcd3279fSFrederic Weisbecker 
436bcd3279fSFrederic Weisbecker 	snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
437bcd3279fSFrederic Weisbecker 		 sys_name, evt_name);
438bcd3279fSFrederic Weisbecker 
439bcd3279fSFrederic Weisbecker 	fd = open(evt_path, O_RDONLY);
440bcd3279fSFrederic Weisbecker 	if (fd < 0)
441bcd3279fSFrederic Weisbecker 		return EVT_FAILED;
442bcd3279fSFrederic Weisbecker 
443bcd3279fSFrederic Weisbecker 	if (read(fd, id_buf, sizeof(id_buf)) < 0) {
444bcd3279fSFrederic Weisbecker 		close(fd);
445bcd3279fSFrederic Weisbecker 		return EVT_FAILED;
446bcd3279fSFrederic Weisbecker 	}
447bcd3279fSFrederic Weisbecker 
448bcd3279fSFrederic Weisbecker 	close(fd);
449bcd3279fSFrederic Weisbecker 	id = atoll(id_buf);
450bcd3279fSFrederic Weisbecker 	attr->config = id;
451bcd3279fSFrederic Weisbecker 	attr->type = PERF_TYPE_TRACEPOINT;
452bcd3279fSFrederic Weisbecker 	*strp = evt_name + evt_length;
453bcd3279fSFrederic Weisbecker 
454bcd3279fSFrederic Weisbecker 	return EVT_HANDLED;
455bcd3279fSFrederic Weisbecker }
456bcd3279fSFrederic Weisbecker 
457bcd3279fSFrederic Weisbecker /* sys + ':' + event + ':' + flags*/
458bcd3279fSFrederic Weisbecker #define MAX_EVOPT_LEN	(MAX_EVENT_LENGTH * 2 + 2 + 128)
459bcd3279fSFrederic Weisbecker static enum event_result
460bcd3279fSFrederic Weisbecker parse_subsystem_tracepoint_event(char *sys_name, char *flags)
461bcd3279fSFrederic Weisbecker {
462bcd3279fSFrederic Weisbecker 	char evt_path[MAXPATHLEN];
463bcd3279fSFrederic Weisbecker 	struct dirent *evt_ent;
464bcd3279fSFrederic Weisbecker 	DIR *evt_dir;
465bcd3279fSFrederic Weisbecker 
466bcd3279fSFrederic Weisbecker 	snprintf(evt_path, MAXPATHLEN, "%s/%s", debugfs_path, sys_name);
467bcd3279fSFrederic Weisbecker 	evt_dir = opendir(evt_path);
468bcd3279fSFrederic Weisbecker 
469bcd3279fSFrederic Weisbecker 	if (!evt_dir) {
470bcd3279fSFrederic Weisbecker 		perror("Can't open event dir");
471bcd3279fSFrederic Weisbecker 		return EVT_FAILED;
472bcd3279fSFrederic Weisbecker 	}
473bcd3279fSFrederic Weisbecker 
474bcd3279fSFrederic Weisbecker 	while ((evt_ent = readdir(evt_dir))) {
475bcd3279fSFrederic Weisbecker 		char event_opt[MAX_EVOPT_LEN + 1];
476bcd3279fSFrederic Weisbecker 		int len;
477bcd3279fSFrederic Weisbecker 		unsigned int rem = MAX_EVOPT_LEN;
478bcd3279fSFrederic Weisbecker 
479bcd3279fSFrederic Weisbecker 		if (!strcmp(evt_ent->d_name, ".")
480bcd3279fSFrederic Weisbecker 		    || !strcmp(evt_ent->d_name, "..")
481bcd3279fSFrederic Weisbecker 		    || !strcmp(evt_ent->d_name, "enable")
482bcd3279fSFrederic Weisbecker 		    || !strcmp(evt_ent->d_name, "filter"))
483bcd3279fSFrederic Weisbecker 			continue;
484bcd3279fSFrederic Weisbecker 
485bcd3279fSFrederic Weisbecker 		len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s", sys_name,
486bcd3279fSFrederic Weisbecker 			       evt_ent->d_name);
487bcd3279fSFrederic Weisbecker 		if (len < 0)
488bcd3279fSFrederic Weisbecker 			return EVT_FAILED;
489bcd3279fSFrederic Weisbecker 
490bcd3279fSFrederic Weisbecker 		rem -= len;
491bcd3279fSFrederic Weisbecker 		if (flags) {
492bcd3279fSFrederic Weisbecker 			if (rem < strlen(flags) + 1)
493bcd3279fSFrederic Weisbecker 				return EVT_FAILED;
494bcd3279fSFrederic Weisbecker 
495bcd3279fSFrederic Weisbecker 			strcat(event_opt, ":");
496bcd3279fSFrederic Weisbecker 			strcat(event_opt, flags);
497bcd3279fSFrederic Weisbecker 		}
498bcd3279fSFrederic Weisbecker 
499bcd3279fSFrederic Weisbecker 		if (parse_events(NULL, event_opt, 0))
500bcd3279fSFrederic Weisbecker 			return EVT_FAILED;
501bcd3279fSFrederic Weisbecker 	}
502bcd3279fSFrederic Weisbecker 
503bcd3279fSFrederic Weisbecker 	return EVT_HANDLED_ALL;
504bcd3279fSFrederic Weisbecker }
505bcd3279fSFrederic Weisbecker 
506bcd3279fSFrederic Weisbecker 
507bcd3279fSFrederic Weisbecker static enum event_result parse_tracepoint_event(const char **strp,
508*cdd6c482SIngo Molnar 				    struct perf_event_attr *attr)
509f6bdafefSJason Baron {
510f6bdafefSJason Baron 	const char *evt_name;
5113a9f131fSFrederic Weisbecker 	char *flags;
512f6bdafefSJason Baron 	char sys_name[MAX_EVENT_LENGTH];
513f6bdafefSJason Baron 	unsigned int sys_length, evt_length;
514f6bdafefSJason Baron 
5155beeded1SJason Baron 	if (valid_debugfs_mount(debugfs_path))
516f6bdafefSJason Baron 		return 0;
517f6bdafefSJason Baron 
518f6bdafefSJason Baron 	evt_name = strchr(*strp, ':');
519f6bdafefSJason Baron 	if (!evt_name)
520bcd3279fSFrederic Weisbecker 		return EVT_FAILED;
521f6bdafefSJason Baron 
522f6bdafefSJason Baron 	sys_length = evt_name - *strp;
523f6bdafefSJason Baron 	if (sys_length >= MAX_EVENT_LENGTH)
524f6bdafefSJason Baron 		return 0;
525f6bdafefSJason Baron 
526f6bdafefSJason Baron 	strncpy(sys_name, *strp, sys_length);
527f6bdafefSJason Baron 	sys_name[sys_length] = '\0';
528f6bdafefSJason Baron 	evt_name = evt_name + 1;
5293a9f131fSFrederic Weisbecker 
5303a9f131fSFrederic Weisbecker 	flags = strchr(evt_name, ':');
5313a9f131fSFrederic Weisbecker 	if (flags) {
5321fc35b29SIngo Molnar 		/* split it out: */
5331fc35b29SIngo Molnar 		evt_name = strndup(evt_name, flags - evt_name);
5343a9f131fSFrederic Weisbecker 		flags++;
5353a9f131fSFrederic Weisbecker 	}
5363a9f131fSFrederic Weisbecker 
537f6bdafefSJason Baron 	evt_length = strlen(evt_name);
538f6bdafefSJason Baron 	if (evt_length >= MAX_EVENT_LENGTH)
539bcd3279fSFrederic Weisbecker 		return EVT_FAILED;
540f6bdafefSJason Baron 
541bcd3279fSFrederic Weisbecker 	if (!strcmp(evt_name, "*")) {
542f6bdafefSJason Baron 		*strp = evt_name + evt_length;
543bcd3279fSFrederic Weisbecker 		return parse_subsystem_tracepoint_event(sys_name, flags);
544bcd3279fSFrederic Weisbecker 	} else
545bcd3279fSFrederic Weisbecker 		return parse_single_tracepoint_event(sys_name, evt_name,
546bcd3279fSFrederic Weisbecker 						     evt_length, flags,
547bcd3279fSFrederic Weisbecker 						     attr, strp);
548f6bdafefSJason Baron }
549f6bdafefSJason Baron 
55074d5b588SJaswinder Singh Rajput static int check_events(const char *str, unsigned int i)
55174d5b588SJaswinder Singh Rajput {
55261c45981SPaul Mackerras 	int n;
55374d5b588SJaswinder Singh Rajput 
55461c45981SPaul Mackerras 	n = strlen(event_symbols[i].symbol);
55561c45981SPaul Mackerras 	if (!strncmp(str, event_symbols[i].symbol, n))
55661c45981SPaul Mackerras 		return n;
55761c45981SPaul Mackerras 
55861c45981SPaul Mackerras 	n = strlen(event_symbols[i].alias);
55961c45981SPaul Mackerras 	if (n)
56061c45981SPaul Mackerras 		if (!strncmp(str, event_symbols[i].alias, n))
56161c45981SPaul Mackerras 			return n;
56261c45981SPaul Mackerras 	return 0;
56361c45981SPaul Mackerras }
56461c45981SPaul Mackerras 
565bcd3279fSFrederic Weisbecker static enum event_result
566*cdd6c482SIngo Molnar parse_symbolic_event(const char **strp, struct perf_event_attr *attr)
56761c45981SPaul Mackerras {
56861c45981SPaul Mackerras 	const char *str = *strp;
56961c45981SPaul Mackerras 	unsigned int i;
57061c45981SPaul Mackerras 	int n;
57161c45981SPaul Mackerras 
57261c45981SPaul Mackerras 	for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
57361c45981SPaul Mackerras 		n = check_events(str, i);
57461c45981SPaul Mackerras 		if (n > 0) {
57561c45981SPaul Mackerras 			attr->type = event_symbols[i].type;
57661c45981SPaul Mackerras 			attr->config = event_symbols[i].config;
57761c45981SPaul Mackerras 			*strp = str + n;
578bcd3279fSFrederic Weisbecker 			return EVT_HANDLED;
57961c45981SPaul Mackerras 		}
58061c45981SPaul Mackerras 	}
581bcd3279fSFrederic Weisbecker 	return EVT_FAILED;
58261c45981SPaul Mackerras }
58361c45981SPaul Mackerras 
584bcd3279fSFrederic Weisbecker static enum event_result
585*cdd6c482SIngo Molnar parse_raw_event(const char **strp, struct perf_event_attr *attr)
58661c45981SPaul Mackerras {
58761c45981SPaul Mackerras 	const char *str = *strp;
58861c45981SPaul Mackerras 	u64 config;
58961c45981SPaul Mackerras 	int n;
59061c45981SPaul Mackerras 
59161c45981SPaul Mackerras 	if (*str != 'r')
592bcd3279fSFrederic Weisbecker 		return EVT_FAILED;
59361c45981SPaul Mackerras 	n = hex2u64(str + 1, &config);
59461c45981SPaul Mackerras 	if (n > 0) {
59561c45981SPaul Mackerras 		*strp = str + n + 1;
59661c45981SPaul Mackerras 		attr->type = PERF_TYPE_RAW;
59761c45981SPaul Mackerras 		attr->config = config;
598bcd3279fSFrederic Weisbecker 		return EVT_HANDLED;
59961c45981SPaul Mackerras 	}
600bcd3279fSFrederic Weisbecker 	return EVT_FAILED;
60161c45981SPaul Mackerras }
60261c45981SPaul Mackerras 
603bcd3279fSFrederic Weisbecker static enum event_result
604*cdd6c482SIngo Molnar parse_numeric_event(const char **strp, struct perf_event_attr *attr)
60561c45981SPaul Mackerras {
60661c45981SPaul Mackerras 	const char *str = *strp;
60761c45981SPaul Mackerras 	char *endp;
60861c45981SPaul Mackerras 	unsigned long type;
60961c45981SPaul Mackerras 	u64 config;
61061c45981SPaul Mackerras 
61161c45981SPaul Mackerras 	type = strtoul(str, &endp, 0);
61261c45981SPaul Mackerras 	if (endp > str && type < PERF_TYPE_MAX && *endp == ':') {
61361c45981SPaul Mackerras 		str = endp + 1;
61461c45981SPaul Mackerras 		config = strtoul(str, &endp, 0);
61561c45981SPaul Mackerras 		if (endp > str) {
61661c45981SPaul Mackerras 			attr->type = type;
61761c45981SPaul Mackerras 			attr->config = config;
61861c45981SPaul Mackerras 			*strp = endp;
619bcd3279fSFrederic Weisbecker 			return EVT_HANDLED;
62061c45981SPaul Mackerras 		}
62161c45981SPaul Mackerras 	}
622bcd3279fSFrederic Weisbecker 	return EVT_FAILED;
62361c45981SPaul Mackerras }
62461c45981SPaul Mackerras 
625bcd3279fSFrederic Weisbecker static enum event_result
626*cdd6c482SIngo Molnar parse_event_modifier(const char **strp, struct perf_event_attr *attr)
62761c45981SPaul Mackerras {
62861c45981SPaul Mackerras 	const char *str = *strp;
62961c45981SPaul Mackerras 	int eu = 1, ek = 1, eh = 1;
63061c45981SPaul Mackerras 
63161c45981SPaul Mackerras 	if (*str++ != ':')
63261c45981SPaul Mackerras 		return 0;
63361c45981SPaul Mackerras 	while (*str) {
63461c45981SPaul Mackerras 		if (*str == 'u')
63561c45981SPaul Mackerras 			eu = 0;
63661c45981SPaul Mackerras 		else if (*str == 'k')
63761c45981SPaul Mackerras 			ek = 0;
63861c45981SPaul Mackerras 		else if (*str == 'h')
63961c45981SPaul Mackerras 			eh = 0;
64061c45981SPaul Mackerras 		else
64161c45981SPaul Mackerras 			break;
64261c45981SPaul Mackerras 		++str;
64361c45981SPaul Mackerras 	}
64461c45981SPaul Mackerras 	if (str >= *strp + 2) {
64561c45981SPaul Mackerras 		*strp = str;
64661c45981SPaul Mackerras 		attr->exclude_user   = eu;
64761c45981SPaul Mackerras 		attr->exclude_kernel = ek;
64861c45981SPaul Mackerras 		attr->exclude_hv     = eh;
64961c45981SPaul Mackerras 		return 1;
65061c45981SPaul Mackerras 	}
65174d5b588SJaswinder Singh Rajput 	return 0;
65274d5b588SJaswinder Singh Rajput }
65374d5b588SJaswinder Singh Rajput 
65486470930SIngo Molnar /*
65586470930SIngo Molnar  * Each event can have multiple symbolic names.
65686470930SIngo Molnar  * Symbolic names are (almost) exactly matched.
65786470930SIngo Molnar  */
658bcd3279fSFrederic Weisbecker static enum event_result
659*cdd6c482SIngo Molnar parse_event_symbols(const char **str, struct perf_event_attr *attr)
66086470930SIngo Molnar {
661bcd3279fSFrederic Weisbecker 	enum event_result ret;
66286470930SIngo Molnar 
663bcd3279fSFrederic Weisbecker 	ret = parse_tracepoint_event(str, attr);
664bcd3279fSFrederic Weisbecker 	if (ret != EVT_FAILED)
665bcd3279fSFrederic Weisbecker 		goto modifier;
666bcd3279fSFrederic Weisbecker 
667bcd3279fSFrederic Weisbecker 	ret = parse_raw_event(str, attr);
668bcd3279fSFrederic Weisbecker 	if (ret != EVT_FAILED)
669bcd3279fSFrederic Weisbecker 		goto modifier;
670bcd3279fSFrederic Weisbecker 
671bcd3279fSFrederic Weisbecker 	ret = parse_numeric_event(str, attr);
672bcd3279fSFrederic Weisbecker 	if (ret != EVT_FAILED)
673bcd3279fSFrederic Weisbecker 		goto modifier;
674bcd3279fSFrederic Weisbecker 
675bcd3279fSFrederic Weisbecker 	ret = parse_symbolic_event(str, attr);
676bcd3279fSFrederic Weisbecker 	if (ret != EVT_FAILED)
677bcd3279fSFrederic Weisbecker 		goto modifier;
678bcd3279fSFrederic Weisbecker 
679bcd3279fSFrederic Weisbecker 	ret = parse_generic_hw_event(str, attr);
680bcd3279fSFrederic Weisbecker 	if (ret != EVT_FAILED)
681bcd3279fSFrederic Weisbecker 		goto modifier;
682bcd3279fSFrederic Weisbecker 
683bcd3279fSFrederic Weisbecker 	return EVT_FAILED;
684bcd3279fSFrederic Weisbecker 
685bcd3279fSFrederic Weisbecker modifier:
68661c45981SPaul Mackerras 	parse_event_modifier(str, attr);
68786470930SIngo Molnar 
688bcd3279fSFrederic Weisbecker 	return ret;
68986470930SIngo Molnar }
69086470930SIngo Molnar 
6918755a8f2SArjan van de Ven static void store_event_type(const char *orgname)
6928755a8f2SArjan van de Ven {
6938755a8f2SArjan van de Ven 	char filename[PATH_MAX], *c;
6948755a8f2SArjan van de Ven 	FILE *file;
6958755a8f2SArjan van de Ven 	int id;
6968755a8f2SArjan van de Ven 
6978755a8f2SArjan van de Ven 	sprintf(filename, "/sys/kernel/debug/tracing/events/%s/id", orgname);
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 {
714*cdd6c482SIngo 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;
7646b58e7f1SUlrich Drepper 	int sys_dir_fd;
765f6bdafefSJason Baron 	char evt_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)
772f6bdafefSJason Baron 		goto cleanup;
7736b58e7f1SUlrich Drepper 	sys_dir_fd = dirfd(sys_dir);
774f6bdafefSJason Baron 
7756b58e7f1SUlrich Drepper 	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
7766b58e7f1SUlrich Drepper 		int dfd = openat(sys_dir_fd, sys_dirent.d_name,
7776b58e7f1SUlrich Drepper 				 O_RDONLY|O_DIRECTORY), evt_dir_fd;
7786b58e7f1SUlrich Drepper 		if (dfd == -1)
7796b58e7f1SUlrich Drepper 			continue;
7806b58e7f1SUlrich Drepper 		evt_dir = fdopendir(dfd);
7816b58e7f1SUlrich Drepper 		if (!evt_dir) {
7826b58e7f1SUlrich Drepper 			close(dfd);
7836b58e7f1SUlrich Drepper 			continue;
7846b58e7f1SUlrich Drepper 		}
7856b58e7f1SUlrich Drepper 		evt_dir_fd = dirfd(evt_dir);
7866b58e7f1SUlrich Drepper 		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
787f6bdafefSJason Baron 			snprintf(evt_path, MAXPATHLEN, "%s:%s",
788f6bdafefSJason Baron 				 sys_dirent.d_name, evt_dirent.d_name);
78948c2e17fSJason Baron 			fprintf(stderr, "  %-42s [%s]\n", evt_path,
790f6bdafefSJason Baron 				event_type_descriptors[PERF_TYPE_TRACEPOINT+1]);
791f6bdafefSJason Baron 		}
792f6bdafefSJason Baron 		closedir(evt_dir);
793f6bdafefSJason Baron 	}
794f6bdafefSJason Baron 
795f6bdafefSJason Baron cleanup:
796f6bdafefSJason Baron 	closedir(sys_dir);
797f6bdafefSJason Baron }
798f6bdafefSJason Baron 
799f6bdafefSJason Baron /*
80086470930SIngo Molnar  * Print the help text for the event symbols:
80186470930SIngo Molnar  */
80286470930SIngo Molnar void print_events(void)
80386470930SIngo Molnar {
80486470930SIngo Molnar 	struct event_symbol *syms = event_symbols;
80573c24cb8SJaswinder Singh Rajput 	unsigned int i, type, op, prev_type = -1;
80674d5b588SJaswinder Singh Rajput 	char name[40];
80786470930SIngo Molnar 
80886470930SIngo Molnar 	fprintf(stderr, "\n");
80986470930SIngo Molnar 	fprintf(stderr, "List of pre-defined events (to be used in -e):\n");
81086470930SIngo Molnar 
81186470930SIngo Molnar 	for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
81286470930SIngo Molnar 		type = syms->type + 1;
81323cdb5d5SRoel Kluin 		if (type >= ARRAY_SIZE(event_type_descriptors))
81486470930SIngo Molnar 			type = 0;
81586470930SIngo Molnar 
81686470930SIngo Molnar 		if (type != prev_type)
81786470930SIngo Molnar 			fprintf(stderr, "\n");
81886470930SIngo Molnar 
81974d5b588SJaswinder Singh Rajput 		if (strlen(syms->alias))
82074d5b588SJaswinder Singh Rajput 			sprintf(name, "%s OR %s", syms->symbol, syms->alias);
82174d5b588SJaswinder Singh Rajput 		else
82274d5b588SJaswinder Singh Rajput 			strcpy(name, syms->symbol);
82348c2e17fSJason Baron 		fprintf(stderr, "  %-42s [%s]\n", name,
82486470930SIngo Molnar 			event_type_descriptors[type]);
82586470930SIngo Molnar 
82686470930SIngo Molnar 		prev_type = type;
82786470930SIngo Molnar 	}
82886470930SIngo Molnar 
82986470930SIngo Molnar 	fprintf(stderr, "\n");
83073c24cb8SJaswinder Singh Rajput 	for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
83173c24cb8SJaswinder Singh Rajput 		for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
83273c24cb8SJaswinder Singh Rajput 			/* skip invalid cache type */
83373c24cb8SJaswinder Singh Rajput 			if (!is_cache_op_valid(type, op))
83473c24cb8SJaswinder Singh Rajput 				continue;
83573c24cb8SJaswinder Singh Rajput 
83673c24cb8SJaswinder Singh Rajput 			for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
83748c2e17fSJason Baron 				fprintf(stderr, "  %-42s [%s]\n",
83873c24cb8SJaswinder Singh Rajput 					event_cache_name(type, op, i),
83973c24cb8SJaswinder Singh Rajput 					event_type_descriptors[4]);
84073c24cb8SJaswinder Singh Rajput 			}
84173c24cb8SJaswinder Singh Rajput 		}
84273c24cb8SJaswinder Singh Rajput 	}
84373c24cb8SJaswinder Singh Rajput 
84473c24cb8SJaswinder Singh Rajput 	fprintf(stderr, "\n");
84548c2e17fSJason Baron 	fprintf(stderr, "  %-42s [raw hardware event descriptor]\n",
84686470930SIngo Molnar 		"rNNN");
84786470930SIngo Molnar 	fprintf(stderr, "\n");
84886470930SIngo Molnar 
849f6bdafefSJason Baron 	print_tracepoint_events();
850f6bdafefSJason Baron 
85186470930SIngo Molnar 	exit(129);
85286470930SIngo Molnar }
853