xref: /linux/tools/perf/util/parse-events.c (revision 74d5b5889ea71a95d8924c08f8a7c6e2bdcbc0ba)
186470930SIngo Molnar 
286470930SIngo Molnar #include "../perf.h"
386470930SIngo Molnar #include "util.h"
486470930SIngo Molnar #include "parse-options.h"
586470930SIngo Molnar #include "parse-events.h"
686470930SIngo Molnar #include "exec_cmd.h"
786470930SIngo Molnar #include "string.h"
886470930SIngo Molnar 
986470930SIngo Molnar extern char *strcasestr(const char *haystack, const char *needle);
1086470930SIngo Molnar 
1186470930SIngo Molnar int					nr_counters;
1286470930SIngo Molnar 
1386470930SIngo Molnar struct perf_counter_attr		attrs[MAX_COUNTERS];
1486470930SIngo Molnar 
1586470930SIngo Molnar struct event_symbol {
169cffa8d5SPaul Mackerras 	u8	type;
179cffa8d5SPaul Mackerras 	u64	config;
1886470930SIngo Molnar 	char	*symbol;
19*74d5b588SJaswinder Singh Rajput 	char	*alias;
2086470930SIngo Molnar };
2186470930SIngo Molnar 
2251e26842SJaswinder Singh Rajput #define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
2351e26842SJaswinder Singh Rajput #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
2486470930SIngo Molnar 
2586470930SIngo Molnar static struct event_symbol event_symbols[] = {
26*74d5b588SJaswinder Singh Rajput   { CHW(CPU_CYCLES),		"cpu-cycles",		"cycles"	},
27*74d5b588SJaswinder Singh Rajput   { CHW(INSTRUCTIONS),		"instructions",		""		},
28*74d5b588SJaswinder Singh Rajput   { CHW(CACHE_REFERENCES),	"cache-references",	""		},
29*74d5b588SJaswinder Singh Rajput   { CHW(CACHE_MISSES),		"cache-misses",		""		},
30*74d5b588SJaswinder Singh Rajput   { CHW(BRANCH_INSTRUCTIONS),	"branch-instructions",	"branches"	},
31*74d5b588SJaswinder Singh Rajput   { CHW(BRANCH_MISSES),		"branch-misses",	""		},
32*74d5b588SJaswinder Singh Rajput   { CHW(BUS_CYCLES),		"bus-cycles",		""		},
3386470930SIngo Molnar 
34*74d5b588SJaswinder Singh Rajput   { CSW(CPU_CLOCK),		"cpu-clock",		""		},
35*74d5b588SJaswinder Singh Rajput   { CSW(TASK_CLOCK),		"task-clock",		""		},
36*74d5b588SJaswinder Singh Rajput   { CSW(PAGE_FAULTS),		"page-faults",		""		},
37*74d5b588SJaswinder Singh Rajput   { CSW(PAGE_FAULTS),		"faults",		""		},
38*74d5b588SJaswinder Singh Rajput   { CSW(PAGE_FAULTS_MIN),	"minor-faults",		""		},
39*74d5b588SJaswinder Singh Rajput   { CSW(PAGE_FAULTS_MAJ),	"major-faults",		""		},
40*74d5b588SJaswinder Singh Rajput   { CSW(CONTEXT_SWITCHES),	"context-switches",	"cs"		},
41*74d5b588SJaswinder Singh Rajput   { CSW(CPU_MIGRATIONS),	"cpu-migrations",	"migrations"	},
4286470930SIngo Molnar };
4386470930SIngo Molnar 
4486470930SIngo Molnar #define __PERF_COUNTER_FIELD(config, name) \
4586470930SIngo Molnar 	((config & PERF_COUNTER_##name##_MASK) >> PERF_COUNTER_##name##_SHIFT)
4686470930SIngo Molnar 
4786470930SIngo Molnar #define PERF_COUNTER_RAW(config)	__PERF_COUNTER_FIELD(config, RAW)
4886470930SIngo Molnar #define PERF_COUNTER_CONFIG(config)	__PERF_COUNTER_FIELD(config, CONFIG)
4986470930SIngo Molnar #define PERF_COUNTER_TYPE(config)	__PERF_COUNTER_FIELD(config, TYPE)
5086470930SIngo Molnar #define PERF_COUNTER_ID(config)		__PERF_COUNTER_FIELD(config, EVENT)
5186470930SIngo Molnar 
5286470930SIngo Molnar static char *hw_event_names[] = {
5386470930SIngo Molnar 	"cycles",
5486470930SIngo Molnar 	"instructions",
5586470930SIngo Molnar 	"cache-references",
5686470930SIngo Molnar 	"cache-misses",
5786470930SIngo Molnar 	"branches",
5886470930SIngo Molnar 	"branch-misses",
5986470930SIngo Molnar 	"bus-cycles",
6086470930SIngo Molnar };
6186470930SIngo Molnar 
6286470930SIngo Molnar static char *sw_event_names[] = {
6344175b6fSIngo Molnar 	"cpu-clock-msecs",
6444175b6fSIngo Molnar 	"task-clock-msecs",
6586470930SIngo Molnar 	"page-faults",
6686470930SIngo Molnar 	"context-switches",
6786470930SIngo Molnar 	"CPU-migrations",
6886470930SIngo Molnar 	"minor-faults",
6986470930SIngo Molnar 	"major-faults",
7086470930SIngo Molnar };
7186470930SIngo Molnar 
7286470930SIngo Molnar #define MAX_ALIASES 8
7386470930SIngo Molnar 
7486470930SIngo Molnar static char *hw_cache [][MAX_ALIASES] = {
75faafec1eSYong Wang 	{ "L1-data"		, "l1-d", "l1d"					},
7686470930SIngo Molnar 	{ "L1-instruction"	, "l1-i", "l1i"					},
7786470930SIngo Molnar 	{ "L2"			, "l2"						},
7886470930SIngo Molnar 	{ "Data-TLB"		, "dtlb", "d-tlb"				},
7986470930SIngo Molnar 	{ "Instruction-TLB"	, "itlb", "i-tlb"				},
8086470930SIngo Molnar 	{ "Branch"		, "bpu" , "btb", "bpc"				},
8186470930SIngo Molnar };
8286470930SIngo Molnar 
8386470930SIngo Molnar static char *hw_cache_op [][MAX_ALIASES] = {
8486470930SIngo Molnar 	{ "Load"		, "read"					},
8586470930SIngo Molnar 	{ "Store"		, "write"					},
8686470930SIngo Molnar 	{ "Prefetch"		, "speculative-read", "speculative-load"	},
8786470930SIngo Molnar };
8886470930SIngo Molnar 
8986470930SIngo Molnar static char *hw_cache_result [][MAX_ALIASES] = {
9086470930SIngo Molnar 	{ "Reference"		, "ops", "access"				},
9186470930SIngo Molnar 	{ "Miss"								},
9286470930SIngo Molnar };
9386470930SIngo Molnar 
9486470930SIngo Molnar char *event_name(int counter)
9586470930SIngo Molnar {
969cffa8d5SPaul Mackerras 	u64 config = attrs[counter].config;
9786470930SIngo Molnar 	int type = attrs[counter].type;
9886470930SIngo Molnar 	static char buf[32];
9986470930SIngo Molnar 
10086470930SIngo Molnar 	if (attrs[counter].type == PERF_TYPE_RAW) {
10186470930SIngo Molnar 		sprintf(buf, "raw 0x%llx", config);
10286470930SIngo Molnar 		return buf;
10386470930SIngo Molnar 	}
10486470930SIngo Molnar 
10586470930SIngo Molnar 	switch (type) {
10686470930SIngo Molnar 	case PERF_TYPE_HARDWARE:
107f4dbfa8fSPeter Zijlstra 		if (config < PERF_COUNT_HW_MAX)
10886470930SIngo Molnar 			return hw_event_names[config];
10986470930SIngo Molnar 		return "unknown-hardware";
11086470930SIngo Molnar 
11186470930SIngo Molnar 	case PERF_TYPE_HW_CACHE: {
1129cffa8d5SPaul Mackerras 		u8 cache_type, cache_op, cache_result;
11386470930SIngo Molnar 		static char name[100];
11486470930SIngo Molnar 
11586470930SIngo Molnar 		cache_type   = (config >>  0) & 0xff;
11686470930SIngo Molnar 		if (cache_type > PERF_COUNT_HW_CACHE_MAX)
11786470930SIngo Molnar 			return "unknown-ext-hardware-cache-type";
11886470930SIngo Molnar 
11986470930SIngo Molnar 		cache_op     = (config >>  8) & 0xff;
12086470930SIngo Molnar 		if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX)
12186470930SIngo Molnar 			return "unknown-ext-hardware-cache-op";
12286470930SIngo Molnar 
12386470930SIngo Molnar 		cache_result = (config >> 16) & 0xff;
12486470930SIngo Molnar 		if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX)
12586470930SIngo Molnar 			return "unknown-ext-hardware-cache-result";
12686470930SIngo Molnar 
12786470930SIngo Molnar 		sprintf(name, "%s-Cache-%s-%ses",
12886470930SIngo Molnar 			hw_cache[cache_type][0],
12986470930SIngo Molnar 			hw_cache_op[cache_op][0],
13086470930SIngo Molnar 			hw_cache_result[cache_result][0]);
13186470930SIngo Molnar 
13286470930SIngo Molnar 		return name;
13386470930SIngo Molnar 	}
13486470930SIngo Molnar 
13586470930SIngo Molnar 	case PERF_TYPE_SOFTWARE:
136f4dbfa8fSPeter Zijlstra 		if (config < PERF_COUNT_SW_MAX)
13786470930SIngo Molnar 			return sw_event_names[config];
13886470930SIngo Molnar 		return "unknown-software";
13986470930SIngo Molnar 
14086470930SIngo Molnar 	default:
14186470930SIngo Molnar 		break;
14286470930SIngo Molnar 	}
14386470930SIngo Molnar 
14486470930SIngo Molnar 	return "unknown";
14586470930SIngo Molnar }
14686470930SIngo Molnar 
14786470930SIngo Molnar static int parse_aliases(const char *str, char *names[][MAX_ALIASES], int size)
14886470930SIngo Molnar {
14986470930SIngo Molnar 	int i, j;
15086470930SIngo Molnar 
15186470930SIngo Molnar 	for (i = 0; i < size; i++) {
15286470930SIngo Molnar 		for (j = 0; j < MAX_ALIASES; j++) {
15386470930SIngo Molnar 			if (!names[i][j])
15486470930SIngo Molnar 				break;
15586470930SIngo Molnar 			if (strcasestr(str, names[i][j]))
15686470930SIngo Molnar 				return i;
15786470930SIngo Molnar 		}
15886470930SIngo Molnar 	}
15986470930SIngo Molnar 
1608953645fSIngo Molnar 	return -1;
16186470930SIngo Molnar }
16286470930SIngo Molnar 
16386470930SIngo Molnar static int parse_generic_hw_symbols(const char *str, struct perf_counter_attr *attr)
16486470930SIngo Molnar {
1658953645fSIngo Molnar 	int cache_type = -1, cache_op = 0, cache_result = 0;
16686470930SIngo Molnar 
16786470930SIngo Molnar 	cache_type = parse_aliases(str, hw_cache, PERF_COUNT_HW_CACHE_MAX);
16886470930SIngo Molnar 	/*
16986470930SIngo Molnar 	 * No fallback - if we cannot get a clear cache type
17086470930SIngo Molnar 	 * then bail out:
17186470930SIngo Molnar 	 */
17286470930SIngo Molnar 	if (cache_type == -1)
17386470930SIngo Molnar 		return -EINVAL;
17486470930SIngo Molnar 
17586470930SIngo Molnar 	cache_op = parse_aliases(str, hw_cache_op, PERF_COUNT_HW_CACHE_OP_MAX);
17686470930SIngo Molnar 	/*
17786470930SIngo Molnar 	 * Fall back to reads:
17886470930SIngo Molnar 	 */
1798953645fSIngo Molnar 	if (cache_op == -1)
1808953645fSIngo Molnar 		cache_op = PERF_COUNT_HW_CACHE_OP_READ;
18186470930SIngo Molnar 
18286470930SIngo Molnar 	cache_result = parse_aliases(str, hw_cache_result,
18386470930SIngo Molnar 					PERF_COUNT_HW_CACHE_RESULT_MAX);
18486470930SIngo Molnar 	/*
18586470930SIngo Molnar 	 * Fall back to accesses:
18686470930SIngo Molnar 	 */
18786470930SIngo Molnar 	if (cache_result == -1)
18886470930SIngo Molnar 		cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS;
18986470930SIngo Molnar 
19086470930SIngo Molnar 	attr->config = cache_type | (cache_op << 8) | (cache_result << 16);
19186470930SIngo Molnar 	attr->type = PERF_TYPE_HW_CACHE;
19286470930SIngo Molnar 
19386470930SIngo Molnar 	return 0;
19486470930SIngo Molnar }
19586470930SIngo Molnar 
196*74d5b588SJaswinder Singh Rajput static int check_events(const char *str, unsigned int i)
197*74d5b588SJaswinder Singh Rajput {
198*74d5b588SJaswinder Singh Rajput 	if (!strncmp(str, event_symbols[i].symbol,
199*74d5b588SJaswinder Singh Rajput 		     strlen(event_symbols[i].symbol)))
200*74d5b588SJaswinder Singh Rajput 		return 1;
201*74d5b588SJaswinder Singh Rajput 
202*74d5b588SJaswinder Singh Rajput 	if (strlen(event_symbols[i].alias))
203*74d5b588SJaswinder Singh Rajput 		if (!strncmp(str, event_symbols[i].alias,
204*74d5b588SJaswinder Singh Rajput 		      strlen(event_symbols[i].alias)))
205*74d5b588SJaswinder Singh Rajput 			return 1;
206*74d5b588SJaswinder Singh Rajput 	return 0;
207*74d5b588SJaswinder Singh Rajput }
208*74d5b588SJaswinder Singh Rajput 
20986470930SIngo Molnar /*
21086470930SIngo Molnar  * Each event can have multiple symbolic names.
21186470930SIngo Molnar  * Symbolic names are (almost) exactly matched.
21286470930SIngo Molnar  */
21386470930SIngo Molnar static int parse_event_symbols(const char *str, struct perf_counter_attr *attr)
21486470930SIngo Molnar {
2159cffa8d5SPaul Mackerras 	u64 config, id;
21686470930SIngo Molnar 	int type;
21786470930SIngo Molnar 	unsigned int i;
21886470930SIngo Molnar 	const char *sep, *pstr;
21986470930SIngo Molnar 
22086470930SIngo Molnar 	if (str[0] == 'r' && hex2u64(str + 1, &config) > 0) {
22186470930SIngo Molnar 		attr->type = PERF_TYPE_RAW;
22286470930SIngo Molnar 		attr->config = config;
22386470930SIngo Molnar 
22486470930SIngo Molnar 		return 0;
22586470930SIngo Molnar 	}
22686470930SIngo Molnar 
22786470930SIngo Molnar 	pstr = str;
22886470930SIngo Molnar 	sep = strchr(pstr, ':');
22986470930SIngo Molnar 	if (sep) {
23086470930SIngo Molnar 		type = atoi(pstr);
23186470930SIngo Molnar 		pstr = sep + 1;
23286470930SIngo Molnar 		id = atoi(pstr);
23386470930SIngo Molnar 		sep = strchr(pstr, ':');
23486470930SIngo Molnar 		if (sep) {
23586470930SIngo Molnar 			pstr = sep + 1;
23686470930SIngo Molnar 			if (strchr(pstr, 'k'))
23786470930SIngo Molnar 				attr->exclude_user = 1;
23886470930SIngo Molnar 			if (strchr(pstr, 'u'))
23986470930SIngo Molnar 				attr->exclude_kernel = 1;
24086470930SIngo Molnar 		}
24186470930SIngo Molnar 		attr->type = type;
24286470930SIngo Molnar 		attr->config = id;
24386470930SIngo Molnar 
24486470930SIngo Molnar 		return 0;
24586470930SIngo Molnar 	}
24686470930SIngo Molnar 
24786470930SIngo Molnar 	for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
248*74d5b588SJaswinder Singh Rajput 		if (check_events(str, i)) {
24986470930SIngo Molnar 			attr->type = event_symbols[i].type;
25086470930SIngo Molnar 			attr->config = event_symbols[i].config;
25186470930SIngo Molnar 
25286470930SIngo Molnar 			return 0;
25386470930SIngo Molnar 		}
25486470930SIngo Molnar 	}
25586470930SIngo Molnar 
25686470930SIngo Molnar 	return parse_generic_hw_symbols(str, attr);
25786470930SIngo Molnar }
25886470930SIngo Molnar 
25986470930SIngo Molnar int parse_events(const struct option *opt, const char *str, int unset)
26086470930SIngo Molnar {
26186470930SIngo Molnar 	struct perf_counter_attr attr;
26286470930SIngo Molnar 	int ret;
26386470930SIngo Molnar 
26486470930SIngo Molnar 	memset(&attr, 0, sizeof(attr));
26586470930SIngo Molnar again:
26686470930SIngo Molnar 	if (nr_counters == MAX_COUNTERS)
26786470930SIngo Molnar 		return -1;
26886470930SIngo Molnar 
26986470930SIngo Molnar 	ret = parse_event_symbols(str, &attr);
27086470930SIngo Molnar 	if (ret < 0)
27186470930SIngo Molnar 		return ret;
27286470930SIngo Molnar 
27386470930SIngo Molnar 	attrs[nr_counters] = attr;
27486470930SIngo Molnar 	nr_counters++;
27586470930SIngo Molnar 
27686470930SIngo Molnar 	str = strstr(str, ",");
27786470930SIngo Molnar 	if (str) {
27886470930SIngo Molnar 		str++;
27986470930SIngo Molnar 		goto again;
28086470930SIngo Molnar 	}
28186470930SIngo Molnar 
28286470930SIngo Molnar 	return 0;
28386470930SIngo Molnar }
28486470930SIngo Molnar 
28586470930SIngo Molnar static const char * const event_type_descriptors[] = {
28686470930SIngo Molnar 	"",
28786470930SIngo Molnar 	"Hardware event",
28886470930SIngo Molnar 	"Software event",
28986470930SIngo Molnar 	"Tracepoint event",
29086470930SIngo Molnar 	"Hardware cache event",
29186470930SIngo Molnar };
29286470930SIngo Molnar 
29386470930SIngo Molnar /*
29486470930SIngo Molnar  * Print the help text for the event symbols:
29586470930SIngo Molnar  */
29686470930SIngo Molnar void print_events(void)
29786470930SIngo Molnar {
29886470930SIngo Molnar 	struct event_symbol *syms = event_symbols;
29986470930SIngo Molnar 	unsigned int i, type, prev_type = -1;
300*74d5b588SJaswinder Singh Rajput 	char name[40];
30186470930SIngo Molnar 
30286470930SIngo Molnar 	fprintf(stderr, "\n");
30386470930SIngo Molnar 	fprintf(stderr, "List of pre-defined events (to be used in -e):\n");
30486470930SIngo Molnar 
30586470930SIngo Molnar 	for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
30686470930SIngo Molnar 		type = syms->type + 1;
30786470930SIngo Molnar 		if (type > ARRAY_SIZE(event_type_descriptors))
30886470930SIngo Molnar 			type = 0;
30986470930SIngo Molnar 
31086470930SIngo Molnar 		if (type != prev_type)
31186470930SIngo Molnar 			fprintf(stderr, "\n");
31286470930SIngo Molnar 
313*74d5b588SJaswinder Singh Rajput 		if (strlen(syms->alias))
314*74d5b588SJaswinder Singh Rajput 			sprintf(name, "%s OR %s", syms->symbol, syms->alias);
315*74d5b588SJaswinder Singh Rajput 		else
316*74d5b588SJaswinder Singh Rajput 			strcpy(name, syms->symbol);
317*74d5b588SJaswinder Singh Rajput 		fprintf(stderr, "  %-40s [%s]\n", name,
31886470930SIngo Molnar 			event_type_descriptors[type]);
31986470930SIngo Molnar 
32086470930SIngo Molnar 		prev_type = type;
32186470930SIngo Molnar 	}
32286470930SIngo Molnar 
32386470930SIngo Molnar 	fprintf(stderr, "\n");
324*74d5b588SJaswinder Singh Rajput 	fprintf(stderr, "  %-40s [raw hardware event descriptor]\n",
32586470930SIngo Molnar 		"rNNN");
32686470930SIngo Molnar 	fprintf(stderr, "\n");
32786470930SIngo Molnar 
32886470930SIngo Molnar 	exit(129);
32986470930SIngo Molnar }
330