perf tools: Only save the event formats we need
[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 #include "cache.h"
9
10 extern char *strcasestr(const char *haystack, const char *needle);
11
12 int                                     nr_counters;
13
14 struct perf_counter_attr                attrs[MAX_COUNTERS];
15
16 struct event_symbol {
17         u8              type;
18         u64             config;
19         const char      *symbol;
20         const char      *alias;
21 };
22
23 char debugfs_path[MAXPATHLEN];
24
25 #define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
26 #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
27
28 static struct event_symbol event_symbols[] = {
29   { CHW(CPU_CYCLES),            "cpu-cycles",           "cycles"        },
30   { CHW(INSTRUCTIONS),          "instructions",         ""              },
31   { CHW(CACHE_REFERENCES),      "cache-references",     ""              },
32   { CHW(CACHE_MISSES),          "cache-misses",         ""              },
33   { CHW(BRANCH_INSTRUCTIONS),   "branch-instructions",  "branches"      },
34   { CHW(BRANCH_MISSES),         "branch-misses",        ""              },
35   { CHW(BUS_CYCLES),            "bus-cycles",           ""              },
36
37   { CSW(CPU_CLOCK),             "cpu-clock",            ""              },
38   { CSW(TASK_CLOCK),            "task-clock",           ""              },
39   { CSW(PAGE_FAULTS),           "page-faults",          "faults"        },
40   { CSW(PAGE_FAULTS_MIN),       "minor-faults",         ""              },
41   { CSW(PAGE_FAULTS_MAJ),       "major-faults",         ""              },
42   { CSW(CONTEXT_SWITCHES),      "context-switches",     "cs"            },
43   { CSW(CPU_MIGRATIONS),        "cpu-migrations",       "migrations"    },
44 };
45
46 #define __PERF_COUNTER_FIELD(config, name) \
47         ((config & PERF_COUNTER_##name##_MASK) >> PERF_COUNTER_##name##_SHIFT)
48
49 #define PERF_COUNTER_RAW(config)        __PERF_COUNTER_FIELD(config, RAW)
50 #define PERF_COUNTER_CONFIG(config)     __PERF_COUNTER_FIELD(config, CONFIG)
51 #define PERF_COUNTER_TYPE(config)       __PERF_COUNTER_FIELD(config, TYPE)
52 #define PERF_COUNTER_ID(config)         __PERF_COUNTER_FIELD(config, EVENT)
53
54 static const char *hw_event_names[] = {
55         "cycles",
56         "instructions",
57         "cache-references",
58         "cache-misses",
59         "branches",
60         "branch-misses",
61         "bus-cycles",
62 };
63
64 static const char *sw_event_names[] = {
65         "cpu-clock-msecs",
66         "task-clock-msecs",
67         "page-faults",
68         "context-switches",
69         "CPU-migrations",
70         "minor-faults",
71         "major-faults",
72 };
73
74 #define MAX_ALIASES 8
75
76 static const char *hw_cache[][MAX_ALIASES] = {
77  { "L1-dcache", "l1-d",         "l1d",          "L1-data",              },
78  { "L1-icache", "l1-i",         "l1i",          "L1-instruction",       },
79  { "LLC",       "L2"                                                    },
80  { "dTLB",      "d-tlb",        "Data-TLB",                             },
81  { "iTLB",      "i-tlb",        "Instruction-TLB",                      },
82  { "branch",    "branches",     "bpu",          "btb",          "bpc",  },
83 };
84
85 static const char *hw_cache_op[][MAX_ALIASES] = {
86  { "load",      "loads",        "read",                                 },
87  { "store",     "stores",       "write",                                },
88  { "prefetch",  "prefetches",   "speculative-read", "speculative-load", },
89 };
90
91 static const char *hw_cache_result[][MAX_ALIASES] = {
92  { "refs",      "Reference",    "ops",          "access",               },
93  { "misses",    "miss",                                                 },
94 };
95
96 #define C(x)            PERF_COUNT_HW_CACHE_##x
97 #define CACHE_READ      (1 << C(OP_READ))
98 #define CACHE_WRITE     (1 << C(OP_WRITE))
99 #define CACHE_PREFETCH  (1 << C(OP_PREFETCH))
100 #define COP(x)          (1 << x)
101
102 /*
103  * cache operartion stat
104  * L1I : Read and prefetch only
105  * ITLB and BPU : Read-only
106  */
107 static unsigned long hw_cache_stat[C(MAX)] = {
108  [C(L1D)]       = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
109  [C(L1I)]       = (CACHE_READ | CACHE_PREFETCH),
110  [C(LL)]        = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
111  [C(DTLB)]      = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
112  [C(ITLB)]      = (CACHE_READ),
113  [C(BPU)]       = (CACHE_READ),
114 };
115
116 #define for_each_subsystem(sys_dir, sys_dirent, sys_next, file, st)            \
117         while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next)        \
118         if (snprintf(file, MAXPATHLEN, "%s/%s", debugfs_path,                  \
119                         sys_dirent.d_name) &&                                  \
120            (!stat(file, &st)) && (S_ISDIR(st.st_mode)) &&                      \
121            (strcmp(sys_dirent.d_name, ".")) &&                                 \
122            (strcmp(sys_dirent.d_name, "..")))
123
124 static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
125 {
126         char evt_path[MAXPATHLEN];
127         int fd;
128
129         snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
130                         sys_dir->d_name, evt_dir->d_name);
131         fd = open(evt_path, O_RDONLY);
132         if (fd < 0)
133                 return -EINVAL;
134         close(fd);
135
136         return 0;
137 }
138
139 #define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next, file, st)    \
140         while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next)        \
141         if (snprintf(file, MAXPATHLEN, "%s/%s/%s", debugfs_path,               \
142                      sys_dirent.d_name, evt_dirent.d_name) &&                  \
143            (!stat(file, &st)) && (S_ISDIR(st.st_mode)) &&                      \
144            (strcmp(evt_dirent.d_name, ".")) &&                                 \
145            (strcmp(evt_dirent.d_name, "..")) &&                                \
146            (!tp_event_has_id(&sys_dirent, &evt_dirent)))
147
148 #define MAX_EVENT_LENGTH 30
149
150 int valid_debugfs_mount(const char *debugfs)
151 {
152         struct statfs st_fs;
153
154         if (statfs(debugfs, &st_fs) < 0)
155                 return -ENOENT;
156         else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
157                 return -ENOENT;
158         return 0;
159 }
160
161 struct tracepoint_path *tracepoint_id_to_path(u64 config)
162 {
163         struct tracepoint_path *path = NULL;
164         DIR *sys_dir, *evt_dir;
165         struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
166         struct stat st;
167         char id_buf[4];
168         int fd;
169         u64 id;
170         char evt_path[MAXPATHLEN];
171
172         if (valid_debugfs_mount(debugfs_path))
173                 return NULL;
174
175         sys_dir = opendir(debugfs_path);
176         if (!sys_dir)
177                 goto cleanup;
178
179         for_each_subsystem(sys_dir, sys_dirent, sys_next, evt_path, st) {
180                 evt_dir = opendir(evt_path);
181                 if (!evt_dir)
182                         goto cleanup;
183                 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next,
184                                                                 evt_path, st) {
185                         snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id",
186                                  debugfs_path, sys_dirent.d_name,
187                                  evt_dirent.d_name);
188                         fd = open(evt_path, O_RDONLY);
189                         if (fd < 0)
190                                 continue;
191                         if (read(fd, id_buf, sizeof(id_buf)) < 0) {
192                                 close(fd);
193                                 continue;
194                         }
195                         close(fd);
196                         id = atoll(id_buf);
197                         if (id == config) {
198                                 closedir(evt_dir);
199                                 closedir(sys_dir);
200                                 path = calloc(1, sizeof(path));
201                                 path->system = malloc(MAX_EVENT_LENGTH);
202                                 if (!path->system) {
203                                         free(path);
204                                         return NULL;
205                                 }
206                                 path->name = malloc(MAX_EVENT_LENGTH);
207                                 if (!path->name) {
208                                         free(path->system);
209                                         free(path);
210                                         return NULL;
211                                 }
212                                 strncpy(path->system, sys_dirent.d_name,
213                                         MAX_EVENT_LENGTH);
214                                 strncpy(path->name, evt_dirent.d_name,
215                                         MAX_EVENT_LENGTH);
216                                 return path;
217                         }
218                 }
219                 closedir(evt_dir);
220         }
221
222 cleanup:
223         closedir(sys_dir);
224         return NULL;
225 }
226
227 #define TP_PATH_LEN (MAX_EVENT_LENGTH * 2 + 1)
228 static const char *tracepoint_id_to_name(u64 config)
229 {
230         static char buf[TP_PATH_LEN];
231         struct tracepoint_path *path;
232
233         path = tracepoint_id_to_path(config);
234         if (path) {
235                 snprintf(buf, TP_PATH_LEN, "%s:%s", path->system, path->name);
236                 free(path->name);
237                 free(path->system);
238                 free(path);
239         } else
240                 snprintf(buf, TP_PATH_LEN, "%s:%s", "unknown", "unknown");
241
242         return buf;
243 }
244
245 static int is_cache_op_valid(u8 cache_type, u8 cache_op)
246 {
247         if (hw_cache_stat[cache_type] & COP(cache_op))
248                 return 1;       /* valid */
249         else
250                 return 0;       /* invalid */
251 }
252
253 static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
254 {
255         static char name[50];
256
257         if (cache_result) {
258                 sprintf(name, "%s-%s-%s", hw_cache[cache_type][0],
259                         hw_cache_op[cache_op][0],
260                         hw_cache_result[cache_result][0]);
261         } else {
262                 sprintf(name, "%s-%s", hw_cache[cache_type][0],
263                         hw_cache_op[cache_op][1]);
264         }
265
266         return name;
267 }
268
269 const char *event_name(int counter)
270 {
271         u64 config = attrs[counter].config;
272         int type = attrs[counter].type;
273
274         return __event_name(type, config);
275 }
276
277 const char *__event_name(int type, u64 config)
278 {
279         static char buf[32];
280
281         if (type == PERF_TYPE_RAW) {
282                 sprintf(buf, "raw 0x%llx", config);
283                 return buf;
284         }
285
286         switch (type) {
287         case PERF_TYPE_HARDWARE:
288                 if (config < PERF_COUNT_HW_MAX)
289                         return hw_event_names[config];
290                 return "unknown-hardware";
291
292         case PERF_TYPE_HW_CACHE: {
293                 u8 cache_type, cache_op, cache_result;
294
295                 cache_type   = (config >>  0) & 0xff;
296                 if (cache_type > PERF_COUNT_HW_CACHE_MAX)
297                         return "unknown-ext-hardware-cache-type";
298
299                 cache_op     = (config >>  8) & 0xff;
300                 if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX)
301                         return "unknown-ext-hardware-cache-op";
302
303                 cache_result = (config >> 16) & 0xff;
304                 if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX)
305                         return "unknown-ext-hardware-cache-result";
306
307                 if (!is_cache_op_valid(cache_type, cache_op))
308                         return "invalid-cache";
309
310                 return event_cache_name(cache_type, cache_op, cache_result);
311         }
312
313         case PERF_TYPE_SOFTWARE:
314                 if (config < PERF_COUNT_SW_MAX)
315                         return sw_event_names[config];
316                 return "unknown-software";
317
318         case PERF_TYPE_TRACEPOINT:
319                 return tracepoint_id_to_name(config);
320
321         default:
322                 break;
323         }
324
325         return "unknown";
326 }
327
328 static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int size)
329 {
330         int i, j;
331         int n, longest = -1;
332
333         for (i = 0; i < size; i++) {
334                 for (j = 0; j < MAX_ALIASES && names[i][j]; j++) {
335                         n = strlen(names[i][j]);
336                         if (n > longest && !strncasecmp(*str, names[i][j], n))
337                                 longest = n;
338                 }
339                 if (longest > 0) {
340                         *str += longest;
341                         return i;
342                 }
343         }
344
345         return -1;
346 }
347
348 static int
349 parse_generic_hw_event(const char **str, struct perf_counter_attr *attr)
350 {
351         const char *s = *str;
352         int cache_type = -1, cache_op = -1, cache_result = -1;
353
354         cache_type = parse_aliases(&s, hw_cache, PERF_COUNT_HW_CACHE_MAX);
355         /*
356          * No fallback - if we cannot get a clear cache type
357          * then bail out:
358          */
359         if (cache_type == -1)
360                 return 0;
361
362         while ((cache_op == -1 || cache_result == -1) && *s == '-') {
363                 ++s;
364
365                 if (cache_op == -1) {
366                         cache_op = parse_aliases(&s, hw_cache_op,
367                                                 PERF_COUNT_HW_CACHE_OP_MAX);
368                         if (cache_op >= 0) {
369                                 if (!is_cache_op_valid(cache_type, cache_op))
370                                         return 0;
371                                 continue;
372                         }
373                 }
374
375                 if (cache_result == -1) {
376                         cache_result = parse_aliases(&s, hw_cache_result,
377                                                 PERF_COUNT_HW_CACHE_RESULT_MAX);
378                         if (cache_result >= 0)
379                                 continue;
380                 }
381
382                 /*
383                  * Can't parse this as a cache op or result, so back up
384                  * to the '-'.
385                  */
386                 --s;
387                 break;
388         }
389
390         /*
391          * Fall back to reads:
392          */
393         if (cache_op == -1)
394                 cache_op = PERF_COUNT_HW_CACHE_OP_READ;
395
396         /*
397          * Fall back to accesses:
398          */
399         if (cache_result == -1)
400                 cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS;
401
402         attr->config = cache_type | (cache_op << 8) | (cache_result << 16);
403         attr->type = PERF_TYPE_HW_CACHE;
404
405         *str = s;
406         return 1;
407 }
408
409 static int parse_tracepoint_event(const char **strp,
410                                     struct perf_counter_attr *attr)
411 {
412         const char *evt_name;
413         char *flags;
414         char sys_name[MAX_EVENT_LENGTH];
415         char id_buf[4];
416         int fd;
417         unsigned int sys_length, evt_length;
418         u64 id;
419         char evt_path[MAXPATHLEN];
420
421         if (valid_debugfs_mount(debugfs_path))
422                 return 0;
423
424         evt_name = strchr(*strp, ':');
425         if (!evt_name)
426                 return 0;
427
428         sys_length = evt_name - *strp;
429         if (sys_length >= MAX_EVENT_LENGTH)
430                 return 0;
431
432         strncpy(sys_name, *strp, sys_length);
433         sys_name[sys_length] = '\0';
434         evt_name = evt_name + 1;
435
436         flags = strchr(evt_name, ':');
437         if (flags) {
438                 *flags = '\0';
439                 flags++;
440                 if (!strncmp(flags, "record", strlen(flags)))
441                         attr->sample_type |= PERF_SAMPLE_RAW;
442         }
443
444         evt_length = strlen(evt_name);
445         if (evt_length >= MAX_EVENT_LENGTH)
446                 return 0;
447
448         snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
449                  sys_name, evt_name);
450         fd = open(evt_path, O_RDONLY);
451         if (fd < 0)
452                 return 0;
453
454         if (read(fd, id_buf, sizeof(id_buf)) < 0) {
455                 close(fd);
456                 return 0;
457         }
458         close(fd);
459         id = atoll(id_buf);
460         attr->config = id;
461         attr->type = PERF_TYPE_TRACEPOINT;
462         *strp = evt_name + evt_length;
463         return 1;
464 }
465
466 static int check_events(const char *str, unsigned int i)
467 {
468         int n;
469
470         n = strlen(event_symbols[i].symbol);
471         if (!strncmp(str, event_symbols[i].symbol, n))
472                 return n;
473
474         n = strlen(event_symbols[i].alias);
475         if (n)
476                 if (!strncmp(str, event_symbols[i].alias, n))
477                         return n;
478         return 0;
479 }
480
481 static int
482 parse_symbolic_event(const char **strp, struct perf_counter_attr *attr)
483 {
484         const char *str = *strp;
485         unsigned int i;
486         int n;
487
488         for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
489                 n = check_events(str, i);
490                 if (n > 0) {
491                         attr->type = event_symbols[i].type;
492                         attr->config = event_symbols[i].config;
493                         *strp = str + n;
494                         return 1;
495                 }
496         }
497         return 0;
498 }
499
500 static int parse_raw_event(const char **strp, struct perf_counter_attr *attr)
501 {
502         const char *str = *strp;
503         u64 config;
504         int n;
505
506         if (*str != 'r')
507                 return 0;
508         n = hex2u64(str + 1, &config);
509         if (n > 0) {
510                 *strp = str + n + 1;
511                 attr->type = PERF_TYPE_RAW;
512                 attr->config = config;
513                 return 1;
514         }
515         return 0;
516 }
517
518 static int
519 parse_numeric_event(const char **strp, struct perf_counter_attr *attr)
520 {
521         const char *str = *strp;
522         char *endp;
523         unsigned long type;
524         u64 config;
525
526         type = strtoul(str, &endp, 0);
527         if (endp > str && type < PERF_TYPE_MAX && *endp == ':') {
528                 str = endp + 1;
529                 config = strtoul(str, &endp, 0);
530                 if (endp > str) {
531                         attr->type = type;
532                         attr->config = config;
533                         *strp = endp;
534                         return 1;
535                 }
536         }
537         return 0;
538 }
539
540 static int
541 parse_event_modifier(const char **strp, struct perf_counter_attr *attr)
542 {
543         const char *str = *strp;
544         int eu = 1, ek = 1, eh = 1;
545
546         if (*str++ != ':')
547                 return 0;
548         while (*str) {
549                 if (*str == 'u')
550                         eu = 0;
551                 else if (*str == 'k')
552                         ek = 0;
553                 else if (*str == 'h')
554                         eh = 0;
555                 else
556                         break;
557                 ++str;
558         }
559         if (str >= *strp + 2) {
560                 *strp = str;
561                 attr->exclude_user   = eu;
562                 attr->exclude_kernel = ek;
563                 attr->exclude_hv     = eh;
564                 return 1;
565         }
566         return 0;
567 }
568
569 /*
570  * Each event can have multiple symbolic names.
571  * Symbolic names are (almost) exactly matched.
572  */
573 static int parse_event_symbols(const char **str, struct perf_counter_attr *attr)
574 {
575         if (!(parse_tracepoint_event(str, attr) ||
576               parse_raw_event(str, attr) ||
577               parse_numeric_event(str, attr) ||
578               parse_symbolic_event(str, attr) ||
579               parse_generic_hw_event(str, attr)))
580                 return 0;
581
582         parse_event_modifier(str, attr);
583
584         return 1;
585 }
586
587 int parse_events(const struct option *opt __used, const char *str, int unset __used)
588 {
589         struct perf_counter_attr attr;
590
591         for (;;) {
592                 if (nr_counters == MAX_COUNTERS)
593                         return -1;
594
595                 memset(&attr, 0, sizeof(attr));
596                 if (!parse_event_symbols(&str, &attr))
597                         return -1;
598
599                 if (!(*str == 0 || *str == ',' || isspace(*str)))
600                         return -1;
601
602                 attrs[nr_counters] = attr;
603                 nr_counters++;
604
605                 if (*str == 0)
606                         break;
607                 if (*str == ',')
608                         ++str;
609                 while (isspace(*str))
610                         ++str;
611         }
612
613         return 0;
614 }
615
616 static const char * const event_type_descriptors[] = {
617         "",
618         "Hardware event",
619         "Software event",
620         "Tracepoint event",
621         "Hardware cache event",
622 };
623
624 /*
625  * Print the events from <debugfs_mount_point>/tracing/events
626  */
627
628 static void print_tracepoint_events(void)
629 {
630         DIR *sys_dir, *evt_dir;
631         struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
632         struct stat st;
633         char evt_path[MAXPATHLEN];
634
635         if (valid_debugfs_mount(debugfs_path))
636                 return;
637
638         sys_dir = opendir(debugfs_path);
639         if (!sys_dir)
640                 goto cleanup;
641
642         for_each_subsystem(sys_dir, sys_dirent, sys_next, evt_path, st) {
643                 evt_dir = opendir(evt_path);
644                 if (!evt_dir)
645                         goto cleanup;
646                 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next,
647                                                                 evt_path, st) {
648                         snprintf(evt_path, MAXPATHLEN, "%s:%s",
649                                  sys_dirent.d_name, evt_dirent.d_name);
650                         fprintf(stderr, "  %-40s [%s]\n", evt_path,
651                                 event_type_descriptors[PERF_TYPE_TRACEPOINT+1]);
652                 }
653                 closedir(evt_dir);
654         }
655
656 cleanup:
657         closedir(sys_dir);
658 }
659
660 /*
661  * Print the help text for the event symbols:
662  */
663 void print_events(void)
664 {
665         struct event_symbol *syms = event_symbols;
666         unsigned int i, type, op, prev_type = -1;
667         char name[40];
668
669         fprintf(stderr, "\n");
670         fprintf(stderr, "List of pre-defined events (to be used in -e):\n");
671
672         for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
673                 type = syms->type + 1;
674                 if (type >= ARRAY_SIZE(event_type_descriptors))
675                         type = 0;
676
677                 if (type != prev_type)
678                         fprintf(stderr, "\n");
679
680                 if (strlen(syms->alias))
681                         sprintf(name, "%s OR %s", syms->symbol, syms->alias);
682                 else
683                         strcpy(name, syms->symbol);
684                 fprintf(stderr, "  %-40s [%s]\n", name,
685                         event_type_descriptors[type]);
686
687                 prev_type = type;
688         }
689
690         fprintf(stderr, "\n");
691         for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
692                 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
693                         /* skip invalid cache type */
694                         if (!is_cache_op_valid(type, op))
695                                 continue;
696
697                         for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
698                                 fprintf(stderr, "  %-40s [%s]\n",
699                                         event_cache_name(type, op, i),
700                                         event_type_descriptors[4]);
701                         }
702                 }
703         }
704
705         fprintf(stderr, "\n");
706         fprintf(stderr, "  %-40s [raw hardware event descriptor]\n",
707                 "rNNN");
708         fprintf(stderr, "\n");
709
710         print_tracepoint_events();
711
712         exit(129);
713 }