blob: 430f06083201adbad63b77c83928eb5d49ceec9f [file] [log] [blame]
Ingo Molnar8ad8db32009-05-26 11:10:09 +02001
2#include "../perf.h"
3#include "util.h"
4#include "parse-options.h"
5#include "parse-events.h"
6#include "exec_cmd.h"
Arnaldo Carvalho de Meloa0055ae2009-06-01 17:50:19 -03007#include "string.h"
Ingo Molnar8ad8db32009-05-26 11:10:09 +02008
Ingo Molnar8326f442009-06-05 20:22:46 +02009extern char *strcasestr(const char *haystack, const char *needle);
10
Ingo Molnara21ca2c2009-06-06 09:58:57 +020011int nr_counters;
Ingo Molnar8ad8db32009-05-26 11:10:09 +020012
Ingo Molnara21ca2c2009-06-06 09:58:57 +020013struct perf_counter_attr attrs[MAX_COUNTERS];
Ingo Molnar8ad8db32009-05-26 11:10:09 +020014
15struct event_symbol {
Paul Mackerras9cffa8d2009-06-19 22:21:42 +100016 u8 type;
17 u64 config;
Ingo Molnara21ca2c2009-06-06 09:58:57 +020018 char *symbol;
Jaswinder Singh Rajput74d5b582009-06-22 16:44:28 +053019 char *alias;
Ingo Molnar8ad8db32009-05-26 11:10:09 +020020};
21
Jaswinder Singh Rajput51e26842009-06-22 16:43:14 +053022#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
23#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
Ingo Molnar8ad8db32009-05-26 11:10:09 +020024
Ingo Molnara21ca2c2009-06-06 09:58:57 +020025static struct event_symbol event_symbols[] = {
Jaswinder Singh Rajput74d5b582009-06-22 16:44:28 +053026 { CHW(CPU_CYCLES), "cpu-cycles", "cycles" },
27 { CHW(INSTRUCTIONS), "instructions", "" },
28 { CHW(CACHE_REFERENCES), "cache-references", "" },
29 { CHW(CACHE_MISSES), "cache-misses", "" },
30 { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" },
31 { CHW(BRANCH_MISSES), "branch-misses", "" },
32 { CHW(BUS_CYCLES), "bus-cycles", "" },
Ingo Molnara21ca2c2009-06-06 09:58:57 +020033
Jaswinder Singh Rajput74d5b582009-06-22 16:44:28 +053034 { CSW(CPU_CLOCK), "cpu-clock", "" },
35 { CSW(TASK_CLOCK), "task-clock", "" },
Jaswinder Singh Rajputc0c22db2009-06-22 20:47:26 +053036 { CSW(PAGE_FAULTS), "page-faults", "faults" },
Jaswinder Singh Rajput74d5b582009-06-22 16:44:28 +053037 { CSW(PAGE_FAULTS_MIN), "minor-faults", "" },
38 { CSW(PAGE_FAULTS_MAJ), "major-faults", "" },
39 { CSW(CONTEXT_SWITCHES), "context-switches", "cs" },
40 { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" },
Ingo Molnar8ad8db32009-05-26 11:10:09 +020041};
42
Ingo Molnar52425192009-05-26 09:17:18 +020043#define __PERF_COUNTER_FIELD(config, name) \
44 ((config & PERF_COUNTER_##name##_MASK) >> PERF_COUNTER_##name##_SHIFT)
45
46#define PERF_COUNTER_RAW(config) __PERF_COUNTER_FIELD(config, RAW)
47#define PERF_COUNTER_CONFIG(config) __PERF_COUNTER_FIELD(config, CONFIG)
48#define PERF_COUNTER_TYPE(config) __PERF_COUNTER_FIELD(config, TYPE)
49#define PERF_COUNTER_ID(config) __PERF_COUNTER_FIELD(config, EVENT)
50
51static char *hw_event_names[] = {
Ingo Molnar8faf3b52009-06-06 13:58:12 +020052 "cycles",
Ingo Molnar52425192009-05-26 09:17:18 +020053 "instructions",
Ingo Molnar8faf3b52009-06-06 13:58:12 +020054 "cache-references",
55 "cache-misses",
Ingo Molnar52425192009-05-26 09:17:18 +020056 "branches",
Ingo Molnar8faf3b52009-06-06 13:58:12 +020057 "branch-misses",
58 "bus-cycles",
Ingo Molnar52425192009-05-26 09:17:18 +020059};
60
61static char *sw_event_names[] = {
Ingo Molnar44175b62009-06-13 13:35:00 +020062 "cpu-clock-msecs",
63 "task-clock-msecs",
Ingo Molnar8faf3b52009-06-06 13:58:12 +020064 "page-faults",
65 "context-switches",
66 "CPU-migrations",
67 "minor-faults",
68 "major-faults",
Ingo Molnar52425192009-05-26 09:17:18 +020069};
70
Ingo Molnar8326f442009-06-05 20:22:46 +020071#define MAX_ALIASES 8
72
Jaswinder Singh Rajputc0c22db2009-06-22 20:47:26 +053073static char *hw_cache[][MAX_ALIASES] = {
Jaswinder Singh Rajpute5c59542009-06-25 18:25:22 +053074 { "L1-d$", "l1-d", "L1-data", },
75 { "L1-i$", "l1-i", "L1-instruction", },
76 { "LLC", "L2" },
77 { "dTLB", "d-tlb", "Data-TLB", },
78 { "iTLB", "i-tlb", "Instruction-TLB", },
79 { "branch", "branches", "bpu", "btb", "bpc", },
Ingo Molnar8326f442009-06-05 20:22:46 +020080};
81
Jaswinder Singh Rajputc0c22db2009-06-22 20:47:26 +053082static char *hw_cache_op[][MAX_ALIASES] = {
Jaswinder Singh Rajpute5c59542009-06-25 18:25:22 +053083 { "load", "loads", "read", },
84 { "store", "stores", "write", },
85 { "prefetch", "prefetches", "speculative-read", "speculative-load", },
Ingo Molnar8326f442009-06-05 20:22:46 +020086};
87
Jaswinder Singh Rajputc0c22db2009-06-22 20:47:26 +053088static char *hw_cache_result[][MAX_ALIASES] = {
Jaswinder Singh Rajpute5c59542009-06-25 18:25:22 +053089 { "refs", "Reference", "ops", "access", },
90 { "misses", "miss", },
Ingo Molnar8326f442009-06-05 20:22:46 +020091};
92
Jaswinder Singh Rajput06813f62009-06-25 17:16:07 +053093#define C(x) PERF_COUNT_HW_CACHE_##x
94#define CACHE_READ (1 << C(OP_READ))
95#define CACHE_WRITE (1 << C(OP_WRITE))
96#define CACHE_PREFETCH (1 << C(OP_PREFETCH))
97#define COP(x) (1 << x)
98
99/*
100 * cache operartion stat
101 * L1I : Read and prefetch only
102 * ITLB and BPU : Read-only
103 */
104static unsigned long hw_cache_stat[C(MAX)] = {
105 [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
106 [C(L1I)] = (CACHE_READ | CACHE_PREFETCH),
107 [C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
108 [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
109 [C(ITLB)] = (CACHE_READ),
110 [C(BPU)] = (CACHE_READ),
111};
112
113static int is_cache_op_valid(u8 cache_type, u8 cache_op)
114{
115 if (hw_cache_stat[cache_type] & COP(cache_op))
116 return 1; /* valid */
117 else
118 return 0; /* invalid */
119}
120
Jaswinder Singh Rajpute5c59542009-06-25 18:25:22 +0530121static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
122{
123 static char name[50];
124
125 if (cache_result) {
126 sprintf(name, "%s-%s-%s", hw_cache[cache_type][0],
127 hw_cache_op[cache_op][0],
128 hw_cache_result[cache_result][0]);
129 } else {
130 sprintf(name, "%s-%s", hw_cache[cache_type][0],
131 hw_cache_op[cache_op][1]);
132 }
133
134 return name;
135}
136
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200137char *event_name(int counter)
Ingo Molnar52425192009-05-26 09:17:18 +0200138{
Paul Mackerras9cffa8d2009-06-19 22:21:42 +1000139 u64 config = attrs[counter].config;
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200140 int type = attrs[counter].type;
Ingo Molnar52425192009-05-26 09:17:18 +0200141 static char buf[32];
142
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200143 if (attrs[counter].type == PERF_TYPE_RAW) {
144 sprintf(buf, "raw 0x%llx", config);
Ingo Molnar52425192009-05-26 09:17:18 +0200145 return buf;
146 }
147
148 switch (type) {
149 case PERF_TYPE_HARDWARE:
Peter Zijlstraf4dbfa82009-06-11 14:06:28 +0200150 if (config < PERF_COUNT_HW_MAX)
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200151 return hw_event_names[config];
Ingo Molnar52425192009-05-26 09:17:18 +0200152 return "unknown-hardware";
153
Ingo Molnar8326f442009-06-05 20:22:46 +0200154 case PERF_TYPE_HW_CACHE: {
Paul Mackerras9cffa8d2009-06-19 22:21:42 +1000155 u8 cache_type, cache_op, cache_result;
Ingo Molnar8326f442009-06-05 20:22:46 +0200156
157 cache_type = (config >> 0) & 0xff;
158 if (cache_type > PERF_COUNT_HW_CACHE_MAX)
159 return "unknown-ext-hardware-cache-type";
160
161 cache_op = (config >> 8) & 0xff;
Ingo Molnar8faf3b52009-06-06 13:58:12 +0200162 if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX)
163 return "unknown-ext-hardware-cache-op";
Ingo Molnar8326f442009-06-05 20:22:46 +0200164
165 cache_result = (config >> 16) & 0xff;
Ingo Molnar8faf3b52009-06-06 13:58:12 +0200166 if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX)
167 return "unknown-ext-hardware-cache-result";
Ingo Molnar8326f442009-06-05 20:22:46 +0200168
Jaswinder Singh Rajput06813f62009-06-25 17:16:07 +0530169 if (!is_cache_op_valid(cache_type, cache_op))
170 return "invalid-cache";
Ingo Molnar8326f442009-06-05 20:22:46 +0200171
Jaswinder Singh Rajpute5c59542009-06-25 18:25:22 +0530172 return event_cache_name(cache_type, cache_op, cache_result);
Ingo Molnar8326f442009-06-05 20:22:46 +0200173 }
174
Ingo Molnar52425192009-05-26 09:17:18 +0200175 case PERF_TYPE_SOFTWARE:
Peter Zijlstraf4dbfa82009-06-11 14:06:28 +0200176 if (config < PERF_COUNT_SW_MAX)
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200177 return sw_event_names[config];
Ingo Molnar52425192009-05-26 09:17:18 +0200178 return "unknown-software";
179
180 default:
181 break;
182 }
183
184 return "unknown";
185}
186
Ingo Molnar8326f442009-06-05 20:22:46 +0200187static int parse_aliases(const char *str, char *names[][MAX_ALIASES], int size)
188{
189 int i, j;
190
191 for (i = 0; i < size; i++) {
192 for (j = 0; j < MAX_ALIASES; j++) {
193 if (!names[i][j])
194 break;
195 if (strcasestr(str, names[i][j]))
196 return i;
197 }
198 }
199
Ingo Molnar89536452009-06-06 21:04:17 +0200200 return -1;
Ingo Molnar8326f442009-06-05 20:22:46 +0200201}
202
Jaswinder Singh Rajputc0c22db2009-06-22 20:47:26 +0530203static int
204parse_generic_hw_symbols(const char *str, struct perf_counter_attr *attr)
Ingo Molnar8326f442009-06-05 20:22:46 +0200205{
Ingo Molnar89536452009-06-06 21:04:17 +0200206 int cache_type = -1, cache_op = 0, cache_result = 0;
Ingo Molnar8326f442009-06-05 20:22:46 +0200207
208 cache_type = parse_aliases(str, hw_cache, PERF_COUNT_HW_CACHE_MAX);
209 /*
210 * No fallback - if we cannot get a clear cache type
211 * then bail out:
212 */
213 if (cache_type == -1)
214 return -EINVAL;
215
216 cache_op = parse_aliases(str, hw_cache_op, PERF_COUNT_HW_CACHE_OP_MAX);
217 /*
218 * Fall back to reads:
219 */
Ingo Molnar89536452009-06-06 21:04:17 +0200220 if (cache_op == -1)
221 cache_op = PERF_COUNT_HW_CACHE_OP_READ;
Ingo Molnar8326f442009-06-05 20:22:46 +0200222
Jaswinder Singh Rajput06813f62009-06-25 17:16:07 +0530223 if (!is_cache_op_valid(cache_type, cache_op))
224 return -EINVAL;
225
Ingo Molnar8326f442009-06-05 20:22:46 +0200226 cache_result = parse_aliases(str, hw_cache_result,
227 PERF_COUNT_HW_CACHE_RESULT_MAX);
228 /*
229 * Fall back to accesses:
230 */
231 if (cache_result == -1)
232 cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS;
233
234 attr->config = cache_type | (cache_op << 8) | (cache_result << 16);
235 attr->type = PERF_TYPE_HW_CACHE;
236
237 return 0;
238}
239
Jaswinder Singh Rajput74d5b582009-06-22 16:44:28 +0530240static int check_events(const char *str, unsigned int i)
241{
242 if (!strncmp(str, event_symbols[i].symbol,
243 strlen(event_symbols[i].symbol)))
244 return 1;
245
246 if (strlen(event_symbols[i].alias))
247 if (!strncmp(str, event_symbols[i].alias,
Jaswinder Singh Rajputc0c22db2009-06-22 20:47:26 +0530248 strlen(event_symbols[i].alias)))
Jaswinder Singh Rajput74d5b582009-06-22 16:44:28 +0530249 return 1;
250 return 0;
251}
252
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200253/*
254 * Each event can have multiple symbolic names.
255 * Symbolic names are (almost) exactly matched.
256 */
Ingo Molnar8326f442009-06-05 20:22:46 +0200257static int parse_event_symbols(const char *str, struct perf_counter_attr *attr)
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200258{
Paul Mackerras9cffa8d2009-06-19 22:21:42 +1000259 u64 config, id;
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200260 int type;
261 unsigned int i;
Arnaldo Carvalho de Meloa0055ae2009-06-01 17:50:19 -0300262 const char *sep, *pstr;
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200263
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200264 if (str[0] == 'r' && hex2u64(str + 1, &config) > 0) {
265 attr->type = PERF_TYPE_RAW;
266 attr->config = config;
267
268 return 0;
269 }
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200270
Arnaldo Carvalho de Meloa0055ae2009-06-01 17:50:19 -0300271 pstr = str;
272 sep = strchr(pstr, ':');
273 if (sep) {
274 type = atoi(pstr);
275 pstr = sep + 1;
276 id = atoi(pstr);
277 sep = strchr(pstr, ':');
278 if (sep) {
279 pstr = sep + 1;
280 if (strchr(pstr, 'k'))
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200281 attr->exclude_user = 1;
Arnaldo Carvalho de Meloa0055ae2009-06-01 17:50:19 -0300282 if (strchr(pstr, 'u'))
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200283 attr->exclude_kernel = 1;
Arnaldo Carvalho de Meloa0055ae2009-06-01 17:50:19 -0300284 }
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200285 attr->type = type;
286 attr->config = id;
287
288 return 0;
Ingo Molnar52425192009-05-26 09:17:18 +0200289 }
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200290
291 for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
Jaswinder Singh Rajput74d5b582009-06-22 16:44:28 +0530292 if (check_events(str, i)) {
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200293 attr->type = event_symbols[i].type;
294 attr->config = event_symbols[i].config;
295
296 return 0;
297 }
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200298 }
299
Ingo Molnar8326f442009-06-05 20:22:46 +0200300 return parse_generic_hw_symbols(str, attr);
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200301}
302
303int parse_events(const struct option *opt, const char *str, int unset)
304{
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200305 struct perf_counter_attr attr;
306 int ret;
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200307
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200308 memset(&attr, 0, sizeof(attr));
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200309again:
310 if (nr_counters == MAX_COUNTERS)
311 return -1;
312
Ingo Molnar8326f442009-06-05 20:22:46 +0200313 ret = parse_event_symbols(str, &attr);
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200314 if (ret < 0)
315 return ret;
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200316
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200317 attrs[nr_counters] = attr;
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200318 nr_counters++;
319
320 str = strstr(str, ",");
321 if (str) {
322 str++;
323 goto again;
324 }
325
326 return 0;
327}
328
Thomas Gleixner86847b62009-06-06 12:24:17 +0200329static const char * const event_type_descriptors[] = {
330 "",
331 "Hardware event",
332 "Software event",
333 "Tracepoint event",
334 "Hardware cache event",
335};
336
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200337/*
Thomas Gleixner86847b62009-06-06 12:24:17 +0200338 * Print the help text for the event symbols:
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200339 */
Thomas Gleixner86847b62009-06-06 12:24:17 +0200340void print_events(void)
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200341{
Thomas Gleixner86847b62009-06-06 12:24:17 +0200342 struct event_symbol *syms = event_symbols;
343 unsigned int i, type, prev_type = -1;
Jaswinder Singh Rajput74d5b582009-06-22 16:44:28 +0530344 char name[40];
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200345
Thomas Gleixner86847b62009-06-06 12:24:17 +0200346 fprintf(stderr, "\n");
347 fprintf(stderr, "List of pre-defined events (to be used in -e):\n");
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200348
Thomas Gleixner86847b62009-06-06 12:24:17 +0200349 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
350 type = syms->type + 1;
351 if (type > ARRAY_SIZE(event_type_descriptors))
352 type = 0;
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200353
Thomas Gleixner86847b62009-06-06 12:24:17 +0200354 if (type != prev_type)
355 fprintf(stderr, "\n");
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200356
Jaswinder Singh Rajput74d5b582009-06-22 16:44:28 +0530357 if (strlen(syms->alias))
358 sprintf(name, "%s OR %s", syms->symbol, syms->alias);
359 else
360 strcpy(name, syms->symbol);
361 fprintf(stderr, " %-40s [%s]\n", name,
Thomas Gleixner86847b62009-06-06 12:24:17 +0200362 event_type_descriptors[type]);
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200363
Thomas Gleixner86847b62009-06-06 12:24:17 +0200364 prev_type = type;
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200365 }
366
Thomas Gleixner86847b62009-06-06 12:24:17 +0200367 fprintf(stderr, "\n");
Jaswinder Singh Rajput74d5b582009-06-22 16:44:28 +0530368 fprintf(stderr, " %-40s [raw hardware event descriptor]\n",
Thomas Gleixner86847b62009-06-06 12:24:17 +0200369 "rNNN");
370 fprintf(stderr, "\n");
371
372 exit(129);
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200373}