perf_counter tools: Shorten names for events
[linux-2.6.git] / tools / perf / util / parse-events.c
1
2 #include "../perf.h"
3 #include "util.h"
4 #include "parse-options.h"
5 #include "parse-events.h"
6 #include "exec_cmd.h"
7 #include "string.h"
8
9 extern char *strcasestr(const char *haystack, const char *needle);
10
11 int                                     nr_counters;
12
13 struct perf_counter_attr                attrs[MAX_COUNTERS];
14
15 struct event_symbol {
16         u8      type;
17         u64     config;
18         char    *symbol;
19         char    *alias;
20 };
21
22 #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
24
25 static struct event_symbol event_symbols[] = {
26   { 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",           ""              },
33
34   { CSW(CPU_CLOCK),             "cpu-clock",            ""              },
35   { CSW(TASK_CLOCK),            "task-clock",           ""              },
36   { CSW(PAGE_FAULTS),           "page-faults",          "faults"        },
37   { 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"    },
41 };
42
43 #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
51 static char *hw_event_names[] = {
52         "cycles",
53         "instructions",
54         "cache-references",
55         "cache-misses",
56         "branches",
57         "branch-misses",
58         "bus-cycles",
59 };
60
61 static char *sw_event_names[] = {
62         "cpu-clock-msecs",
63         "task-clock-msecs",
64         "page-faults",
65         "context-switches",
66         "CPU-migrations",
67         "minor-faults",
68         "major-faults",
69 };
70
71 #define MAX_ALIASES 8
72
73 static char *hw_cache[][MAX_ALIASES] = {
74  { "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",  },
80 };
81
82 static char *hw_cache_op[][MAX_ALIASES] = {
83  { "load",      "loads",        "read",                                 },
84  { "store",     "stores",       "write",                                },
85  { "prefetch",  "prefetches",   "speculative-read", "speculative-load", },
86 };
87
88 static char *hw_cache_result[][MAX_ALIASES] = {
89  { "refs",      "Reference",    "ops",          "access",               },
90  { "misses",    "miss",                                                 },
91 };
92
93 #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  */
104 static 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
113 static 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
121 static 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
137 char *event_name(int counter)
138 {
139         u64 config = attrs[counter].config;
140         int type = attrs[counter].type;
141         static char buf[32];
142
143         if (attrs[counter].type == PERF_TYPE_RAW) {
144                 sprintf(buf, "raw 0x%llx", config);
145                 return buf;
146         }
147
148         switch (type) {
149         case PERF_TYPE_HARDWARE:
150                 if (config < PERF_COUNT_HW_MAX)
151                         return hw_event_names[config];
152                 return "unknown-hardware";
153
154         case PERF_TYPE_HW_CACHE: {
155                 u8 cache_type, cache_op, cache_result;
156
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;
162                 if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX)
163                         return "unknown-ext-hardware-cache-op";
164
165                 cache_result = (config >> 16) & 0xff;
166                 if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX)
167                         return "unknown-ext-hardware-cache-result";
168
169                 if (!is_cache_op_valid(cache_type, cache_op))
170                         return "invalid-cache";
171
172                 return event_cache_name(cache_type, cache_op, cache_result);
173         }
174
175         case PERF_TYPE_SOFTWARE:
176                 if (config < PERF_COUNT_SW_MAX)
177                         return sw_event_names[config];
178                 return "unknown-software";
179
180         default:
181                 break;
182         }
183
184         return "unknown";
185 }
186
187 static 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
200         return -1;
201 }
202
203 static int
204 parse_generic_hw_symbols(const char *str, struct perf_counter_attr *attr)
205 {
206         int cache_type = -1, cache_op = 0, cache_result = 0;
207
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          */
220         if (cache_op == -1)
221                 cache_op = PERF_COUNT_HW_CACHE_OP_READ;
222
223         if (!is_cache_op_valid(cache_type, cache_op))
224                 return -EINVAL;
225
226         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
240 static 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,
248                              strlen(event_symbols[i].alias)))
249                         return 1;
250         return 0;
251 }
252
253 /*
254  * Each event can have multiple symbolic names.
255  * Symbolic names are (almost) exactly matched.
256  */
257 static int parse_event_symbols(const char *str, struct perf_counter_attr *attr)
258 {
259         u64 config, id;
260         int type;
261         unsigned int i;
262         const char *sep, *pstr;
263
264         if (str[0] == 'r' && hex2u64(str + 1, &config) > 0) {
265                 attr->type = PERF_TYPE_RAW;
266                 attr->config = config;
267
268                 return 0;
269         }
270
271         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'))
281                                 attr->exclude_user = 1;
282                         if (strchr(pstr, 'u'))
283                                 attr->exclude_kernel = 1;
284                 }
285                 attr->type = type;
286                 attr->config = id;
287
288                 return 0;
289         }
290
291         for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
292                 if (check_events(str, i)) {
293                         attr->type = event_symbols[i].type;
294                         attr->config = event_symbols[i].config;
295
296                         return 0;
297                 }
298         }
299
300         return parse_generic_hw_symbols(str, attr);
301 }
302
303 int parse_events(const struct option *opt, const char *str, int unset)
304 {
305         struct perf_counter_attr attr;
306         int ret;
307
308         memset(&attr, 0, sizeof(attr));
309 again:
310         if (nr_counters == MAX_COUNTERS)
311                 return -1;
312
313         ret = parse_event_symbols(str, &attr);
314         if (ret < 0)
315                 return ret;
316
317         attrs[nr_counters] = attr;
318         nr_counters++;
319
320         str = strstr(str, ",");
321         if (str) {
322                 str++;
323                 goto again;
324         }
325
326         return 0;
327 }
328
329 static const char * const event_type_descriptors[] = {
330         "",
331         "Hardware event",
332         "Software event",
333         "Tracepoint event",
334         "Hardware cache event",
335 };
336
337 /*
338  * Print the help text for the event symbols:
339  */
340 void print_events(void)
341 {
342         struct event_symbol *syms = event_symbols;
343         unsigned int i, type, prev_type = -1;
344         char name[40];
345
346         fprintf(stderr, "\n");
347         fprintf(stderr, "List of pre-defined events (to be used in -e):\n");
348
349         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;
353
354                 if (type != prev_type)
355                         fprintf(stderr, "\n");
356
357                 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,
362                         event_type_descriptors[type]);
363
364                 prev_type = type;
365         }
366
367         fprintf(stderr, "\n");
368         fprintf(stderr, "  %-40s [raw hardware event descriptor]\n",
369                 "rNNN");
370         fprintf(stderr, "\n");
371
372         exit(129);
373 }