perf: Report maximum values for counter overflow
[akaros.git] / tools / profile / perf / perf_core.c
1 /* Copyright (c) 2015-2016 Google Inc
2  * Davide Libenzi <dlibenzi@google.com>
3  * Barret Rhoden <brho@cs.berkeley.edu>
4  * Stephane Eranian <eranian@gmail.com> (perf_show_event_info() from libpfm4)
5  *
6  * See LICENSE for details. */
7
8 #include <ros/arch/msr-index.h>
9 #include <ros/arch/perfmon.h>
10 #include <ros/common.h>
11 #include <ros/memops.h>
12 #include <sys/types.h>
13 #include <stdint.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include <ctype.h>
19 #include <limits.h>
20 #include <errno.h>
21 #include <regex.h>
22 #include <parlib/parlib.h>
23 #include <perfmon/err.h>
24 #include <perfmon/pfmlib.h>
25 #include "xlib.h"
26 #include "perfconv.h"
27 #include "akaros.h"
28 #include "perf_core.h"
29 #include "elf.h"
30
31 struct perf_generic_event {
32         char                                            *name;
33         uint32_t                                        type;
34         uint32_t                                        config;
35 };
36
37 struct perf_generic_event generic_events[] = {
38         { .name = "cycles",
39           .type = PERF_TYPE_HARDWARE,
40           .config = PERF_COUNT_HW_CPU_CYCLES,
41         },
42         { .name = "cpu-cycles",
43           .type = PERF_TYPE_HARDWARE,
44           .config = PERF_COUNT_HW_CPU_CYCLES,
45         },
46         { .name = "instructions",
47           .type = PERF_TYPE_HARDWARE,
48           .config = PERF_COUNT_HW_INSTRUCTIONS,
49         },
50         { .name = "cache-references",
51           .type = PERF_TYPE_HARDWARE,
52           .config = PERF_COUNT_HW_CACHE_REFERENCES,
53         },
54         { .name = "cache-misses",
55           .type = PERF_TYPE_HARDWARE,
56           .config = PERF_COUNT_HW_CACHE_MISSES,
57         },
58         { .name = "branches",
59           .type = PERF_TYPE_HARDWARE,
60           .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS,
61         },
62         { .name = "branch-instructions",
63           .type = PERF_TYPE_HARDWARE,
64           .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS,
65         },
66         { .name = "branch-misses",
67           .type = PERF_TYPE_HARDWARE,
68           .config = PERF_COUNT_HW_BRANCH_MISSES,
69         },
70         { .name = "bus-cycles",
71           .type = PERF_TYPE_HARDWARE,
72           .config = PERF_COUNT_HW_BUS_CYCLES,
73         },
74 };
75
76 static const char *perf_get_event_mask_name(const pfm_event_info_t *einfo,
77                                                                                         uint32_t mask)
78 {
79         int i;
80         pfm_event_attr_info_t ainfo;
81
82         ZERO_DATA(ainfo);
83         ainfo.size = sizeof(ainfo);
84         pfm_for_each_event_attr(i, einfo) {
85                 pfm_err_t err = pfm_get_event_attr_info(einfo->idx, i, PFM_OS_NONE,
86                                                                                                 &ainfo);
87
88                 if (err != PFM_SUCCESS) {
89                         fprintf(stderr, "Failed to get attribute info: %s\n",
90                                         pfm_strerror(err));
91                         exit(1);
92                 }
93                 if (ainfo.type == PFM_ATTR_UMASK) {
94                         if (mask == (uint32_t) ainfo.code)
95                                 return ainfo.name;
96                 }
97         }
98
99         return NULL;
100 }
101
102 void perf_initialize(void)
103 {
104         pfm_err_t err = pfm_initialize();
105
106         if (err != PFM_SUCCESS) {
107                 fprintf(stderr, "Unable to initialize perfmon library: %s\n",
108                                 pfm_strerror(err));
109                 exit(1);
110         }
111         symbol__elf_init();
112 }
113
114 void perf_finalize(void)
115 {
116         pfm_terminate();
117 }
118
119 /* This is arch-specific and maybe model specific in the future.  For some
120  * events, pfm4 gives us a pseudo encoding.  Those codes don't map to real
121  * hardware events and are meant to be interpreted by Linux for *other* HW
122  * events, e.g. in arch/x86/events/intel/core.c.
123  *
124  * While we're here, we can also take *real* encodings and treat them like
125  * pseudo encodings.  For instance, the arch event 0x3c (unhalted_core_cycles)
126  * can also be done with fixed counter 1.  This all assumes we have version 2 or
127  * later of Intel's perfmon. */
128 static void x86_handle_pseudo_encoding(struct perf_eventsel *sel)
129 {
130         uint8_t lower_byte;
131
132         switch (sel->ev.event & 0xffff) {
133         case 0xc0:      /* arch inst_retired */
134                 sel->ev.flags |= PERFMON_FIXED_EVENT;
135                 PMEV_SET_MASK(sel->ev.event, 0);
136                 PMEV_SET_EVENT(sel->ev.event, 0);
137                 return;
138         case 0x3c:      /* arch unhalted_core_cycles */
139                 sel->ev.flags |= PERFMON_FIXED_EVENT;
140                 PMEV_SET_MASK(sel->ev.event, 0);
141                 PMEV_SET_EVENT(sel->ev.event, 1);
142                 return;
143         case 0x13c:     /* arch unhalted_reference_cycles */
144         case 0x300:     /* pseudo encode: unhalted_reference_cycles */
145                 sel->ev.flags |= PERFMON_FIXED_EVENT;
146                 PMEV_SET_MASK(sel->ev.event, 0);
147                 PMEV_SET_EVENT(sel->ev.event, 2);
148                 return;
149         };
150         lower_byte = sel->ev.event & 0xff;
151         if ((lower_byte == 0x00) || (lower_byte == 0xff))
152                 fprintf(stderr, "Unhandled pseudo encoding %d\n", lower_byte);
153 }
154
155 /* Parse the string using pfm's lookup functions.  Returns TRUE on success and
156  * fills in parts of sel. */
157 static bool parse_pfm_encoding(const char *str, struct perf_eventsel *sel)
158 {
159         pfm_pmu_encode_arg_t encode;
160         int err;
161         char *ptr;
162
163         memset(&encode, 0, sizeof(encode));
164         encode.size = sizeof(encode);
165         encode.fstr = &ptr;
166         err = pfm_get_os_event_encoding(str, PFM_PLM3 | PFM_PLM0, PFM_OS_NONE,
167                                         &encode);
168         if (err)
169                 return FALSE;
170         strlcpy(sel->fq_str, ptr, MAX_FQSTR_SZ);
171         free(ptr);
172         if (encode.count == 0) {
173                 fprintf(stderr, "Found event %s, but it had no codes!\n", sel->fq_str);
174                 return FALSE;
175         }
176         sel->ev.event = encode.codes[0];
177         x86_handle_pseudo_encoding(sel);
178         sel->type = PERF_TYPE_RAW;
179         sel->config = PMEV_GET_MASK(sel->ev.event) | PMEV_GET_EVENT(sel->ev.event);
180         return TRUE;
181 }
182
183 static bool is_end_of_raw(char c)
184 {
185         return (c == ':') || (c == '\0');
186 }
187
188 /* Helper: given a string, if the event is a raw hex code, return its numeric
189  * value.  Returns -1 if it does not match a raw code.
190  *
191  * rNN[N][N][:,\0].  Begins with r, has at least two hexdigits, up to 4, and
192  * ends with : , or \0. */
193 static int extract_raw_code(const char *event)
194 {
195         int i;
196         char copy[5] = {0};
197
198         if (event[0] != 'r')
199                 return -1;
200         event++;
201         for (i = 0; i < 4; i++) {
202                 if (isxdigit(event[i]))
203                         continue;
204                 if (is_end_of_raw(event[i]))
205                         break;
206                 return -1;
207         }
208         if (!is_end_of_raw(event[i]))
209                 return -1;
210         /* 'i' tracks how many we found (i.e. every 'continue') */
211         if (i < 2)
212                 return -1;
213         /* need a null-terminated raw code for strtol. */
214         for (int j = 0; j < i; j++)
215                 copy[j] = event[j];
216         return strtol(copy, NULL, 16);
217 }
218
219 /* Takes any modifiers, e.g. u:k:etc, and sets the respective values in sel. */
220 static void parse_modifiers(const char *str, struct perf_eventsel *sel)
221 {
222         char *dup_str, *tok, *tok_save = 0;
223
224         dup_str = xstrdup(str);
225         for (tok = strtok_r(dup_str, ":", &tok_save);
226              tok;
227              tok = strtok_r(NULL, ":", &tok_save)) {
228
229                 switch (tok[0]) {
230                 case 'u':
231                         PMEV_SET_USR(sel->ev.event, 1);
232                         break;
233                 case 'k':
234                         PMEV_SET_OS(sel->ev.event, 1);
235                         break;
236                 case 'e':
237                         PMEV_SET_EDGE(sel->ev.event, 1);
238                         break;
239                 case 'p':
240                         PMEV_SET_PC(sel->ev.event, 1);
241                         break;
242                 case 't':
243                         PMEV_SET_ANYTH(sel->ev.event, 1);
244                         break;
245                 case 'i':
246                         PMEV_SET_INVCMSK(sel->ev.event, 1);
247                         break;
248                 case 'c':
249                         if (tok[1] != '=') {
250                                 fprintf(stderr, "Bad cmask tok %s, ignoring\n", tok);
251                                 break;
252                         }
253                         errno = 0;
254                         PMEV_SET_CMASK(sel->ev.event, strtoul(&tok[2], NULL, 0));
255                         if (errno)
256                                 fprintf(stderr, "Bad cmask tok %s, trying anyway\n", tok);
257                         break;
258                 }
259         }
260         free(dup_str);
261 }
262
263 /* Parse the string for a raw encoding.  Returns TRUE on success and fills in
264  * parts of sel.  It has basic modifiers, like pfm4, for setting bits in the
265  * event code.  This is arch specific, and is all x86 (intel) for now. */
266 static bool parse_raw_encoding(const char *str, struct perf_eventsel *sel)
267 {
268         int code = extract_raw_code(str);
269         char *colon;
270
271         if (code == -1)
272                 return FALSE;
273         sel->ev.event = code;
274         strlcpy(sel->fq_str, str, MAX_FQSTR_SZ);
275         colon = strchr(str, ':');
276         if (colon)
277                 parse_modifiers(colon + 1, sel);
278         /* Note that we do not call x86_handle_pseudo_encoding here.  We'll submit
279          * exactly what the user asked us for - which also means no fixed counters
280          * for them (unless we want a :f: token or something). */
281         sel->type = PERF_TYPE_RAW;
282         sel->config = PMEV_GET_MASK(sel->ev.event) | PMEV_GET_EVENT(sel->ev.event);
283         return TRUE;
284 }
285
286 /* Helper, returns true is str is a generic event string, and fills in sel with
287  * the type and config. */
288 static bool generic_str_get_code(const char *str, struct perf_eventsel *sel)
289 {
290         char *colon = strchr(str, ':');
291         /* if there was no :, we compare as far as we can.  generic_events.name is a
292          * string literal, so strcmp() is fine. */
293         size_t len = colon ? colon - str : SIZE_MAX;
294
295         for (int i = 0; i < COUNT_OF(generic_events); i++) {
296                 if (!strncmp(generic_events[i].name, str, len)) {
297                         sel->type = generic_events[i].type;
298                         sel->config = generic_events[i].config;
299                         return TRUE;
300                 }
301         }
302         return FALSE;
303 }
304
305 /* TODO: this is arch-specific and possibly machine-specific. (intel for now).
306  * Basically a lot of our perf is arch-dependent. (e.g. PMEV_*). */
307 static bool arch_translate_generic(struct perf_eventsel *sel)
308 {
309         switch (sel->type) {
310         case PERF_TYPE_HARDWARE:
311                 /* These are the intel/x86 architectural perf events */
312                 switch (sel->config) {
313                 case PERF_COUNT_HW_CPU_CYCLES:
314                         PMEV_SET_MASK(sel->ev.event, 0x00);
315                         PMEV_SET_EVENT(sel->ev.event, 0x3c);
316                         break;
317                 case PERF_COUNT_HW_INSTRUCTIONS:
318                         PMEV_SET_MASK(sel->ev.event, 0x00);
319                         PMEV_SET_EVENT(sel->ev.event, 0xc0);
320                         break;
321                 case PERF_COUNT_HW_CACHE_REFERENCES:
322                         PMEV_SET_MASK(sel->ev.event, 0x4f);
323                         PMEV_SET_EVENT(sel->ev.event, 0x2e);
324                         break;
325                 case PERF_COUNT_HW_CACHE_MISSES:
326                         PMEV_SET_MASK(sel->ev.event, 0x41);
327                         PMEV_SET_EVENT(sel->ev.event, 0x2e);
328                         break;
329                 case PERF_COUNT_HW_BRANCH_INSTRUCTIONS:
330                         PMEV_SET_MASK(sel->ev.event, 0x00);
331                         PMEV_SET_EVENT(sel->ev.event, 0xc4);
332                         break;
333                 case PERF_COUNT_HW_BRANCH_MISSES:
334                         PMEV_SET_MASK(sel->ev.event, 0x00);
335                         PMEV_SET_EVENT(sel->ev.event, 0xc5);
336                         break;
337                 case PERF_COUNT_HW_BUS_CYCLES:
338                         /* Unhalted reference cycles */
339                         PMEV_SET_MASK(sel->ev.event, 0x01);
340                         PMEV_SET_EVENT(sel->ev.event, 0x3c);
341                         break;
342                 default:
343                         return FALSE;
344                 };
345                 break;
346         default:
347                 return FALSE;
348         };
349         /* This will make sure we use fixed counters if available */
350         x86_handle_pseudo_encoding(sel);
351         return TRUE;
352 }
353
354 /* Parse the string for a built-in encoding.  These are the perf defaults such
355  * as 'cycles' or 'cache-references.' Returns TRUE on success and fills in parts
356  * of sel. */
357 static bool parse_generic_encoding(const char *str, struct perf_eventsel *sel)
358 {
359         bool ret = FALSE;
360         char *colon;
361
362         if (!generic_str_get_code(str, sel))
363                 return FALSE;
364         switch (sel->type) {
365         case PERF_TYPE_HARDWARE:
366         case PERF_TYPE_HW_CACHE:
367                 ret = arch_translate_generic(sel);
368                 break;
369         };
370         if (!ret) {
371                 fprintf(stderr, "Unsupported built-in event %s\n", str);
372                 return FALSE;
373         }
374         strlcpy(sel->fq_str, str, MAX_FQSTR_SZ);
375         colon = strchr(str, ':');
376         if (colon)
377                 parse_modifiers(colon + 1, sel);
378         return TRUE;
379 }
380
381 /* Given an event description string, fills out sel with the info from the
382  * string such that it can be submitted to the OS.
383  *
384  * The caller can set more bits if they like, such as whether or not to
385  * interrupt on overflow, the sample_period, etc.  None of those settings are
386  * part of the event string.
387  *
388  * Kills the program on failure. */
389 struct perf_eventsel *perf_parse_event(const char *str)
390 {
391         struct perf_eventsel *sel = xzmalloc(sizeof(struct perf_eventsel));
392
393         sel->ev.user_data = (uint64_t)sel;
394         if (parse_generic_encoding(str, sel))
395                 goto success;
396         if (parse_pfm_encoding(str, sel))
397                 goto success;
398         if (parse_raw_encoding(str, sel))
399                 goto success;
400         free(sel);
401         fprintf(stderr, "Failed to parse event string %s\n", str);
402         exit(-1);
403 success:
404         if (!PMEV_GET_OS(sel->ev.event) && !PMEV_GET_USR(sel->ev.event)) {
405                 PMEV_SET_OS(sel->ev.event, 1);
406                 PMEV_SET_USR(sel->ev.event, 1);
407         }
408         PMEV_SET_EN(sel->ev.event, 1);
409         return sel;
410 }
411
412 static void perf_get_arch_info(int perf_fd, struct perf_arch_info *pai)
413 {
414         uint8_t cmdbuf[6 * sizeof(uint32_t)];
415         const uint8_t *rptr = cmdbuf;
416
417         cmdbuf[0] = PERFMON_CMD_CPU_CAPS;
418
419         xpwrite(perf_fd, cmdbuf, 1, 0);
420         xpread(perf_fd, cmdbuf, 6 * sizeof(uint32_t), 0);
421
422         rptr = get_le_u32(rptr, &pai->perfmon_version);
423         rptr = get_le_u32(rptr, &pai->proc_arch_events);
424         rptr = get_le_u32(rptr, &pai->bits_x_counter);
425         rptr = get_le_u32(rptr, &pai->counters_x_proc);
426         rptr = get_le_u32(rptr, &pai->bits_x_fix_counter);
427         rptr = get_le_u32(rptr, &pai->fix_counters_x_proc);
428 }
429
430 static int perf_open_event(int perf_fd, const struct core_set *cores,
431                                                    const struct perf_eventsel *sel)
432 {
433         uint8_t cmdbuf[1 + 3 * sizeof(uint64_t) + sizeof(uint32_t) +
434                                    CORE_SET_SIZE];
435         uint8_t *wptr = cmdbuf;
436         const uint8_t *rptr = cmdbuf;
437         uint32_t ped;
438         int i, j;
439
440         *wptr++ = PERFMON_CMD_COUNTER_OPEN;
441         wptr = put_le_u64(wptr, sel->ev.event);
442         wptr = put_le_u64(wptr, sel->ev.flags);
443         wptr = put_le_u64(wptr, sel->ev.trigger_count);
444         wptr = put_le_u64(wptr, sel->ev.user_data);
445
446         for (i = CORE_SET_SIZE - 1; (i >= 0) && !cores->core_set[i]; i--)
447                 ;
448         if (i < 0) {
449                 fprintf(stderr, "Performance event CPU set must not be empty\n");
450                 exit(1);
451         }
452         wptr = put_le_u32(wptr, i + 1);
453         for (j = 0; j <= i; j++)
454                 *wptr++ = cores->core_set[j];
455
456         xpwrite(perf_fd, cmdbuf, wptr - cmdbuf, 0);
457         xpread(perf_fd, cmdbuf, sizeof(uint32_t), 0);
458
459         rptr = get_le_u32(rptr, &ped);
460
461         return (int) ped;
462 }
463
464 static uint64_t *perf_get_event_values(int perf_fd, int ped, size_t *pnvalues)
465 {
466         ssize_t rsize;
467         uint32_t i, n;
468         uint64_t *values;
469         uint64_t temp;
470         size_t bufsize = sizeof(uint32_t) + MAX_NUM_CORES * sizeof(uint64_t);
471         uint8_t *cmdbuf = xmalloc(bufsize);
472         uint8_t *wptr = cmdbuf;
473         const uint8_t *rptr = cmdbuf;
474
475         *wptr++ = PERFMON_CMD_COUNTER_STATUS;
476         wptr = put_le_u32(wptr, ped);
477
478         xpwrite(perf_fd, cmdbuf, wptr - cmdbuf, 0);
479         rsize = pread(perf_fd, cmdbuf, bufsize, 0);
480
481         if (rsize < (sizeof(uint32_t))) {
482                 fprintf(stderr, "Invalid read size while fetching event status: %ld\n",
483                                 rsize);
484                 exit(1);
485         }
486         rptr = get_le_u32(rptr, &n);
487         if (((rptr - cmdbuf) + n * sizeof(uint64_t)) > rsize) {
488                 fprintf(stderr, "Invalid read size while fetching event status: %ld\n",
489                                 rsize);
490                 exit(1);
491         }
492         values = xmalloc(n * sizeof(uint64_t));
493         for (i = 0; i < n; i++)
494                 rptr = get_le_u64(rptr, values + i);
495         free(cmdbuf);
496
497         *pnvalues = n;
498
499         return values;
500 }
501
502 /* Helper, returns the total count (across all cores) of the event @idx */
503 uint64_t perf_get_event_count(struct perf_context *pctx, unsigned int idx)
504 {
505         uint64_t total = 0;
506         size_t nvalues;
507         uint64_t *values;
508
509         values = perf_get_event_values(pctx->perf_fd, pctx->events[idx].ped,
510                                        &nvalues);
511         for (int i = 0; i < nvalues; i++)
512                 total += values[i];
513         free(values);
514         return total;
515 }
516
517 static void perf_close_event(int perf_fd, int ped)
518 {
519         uint8_t cmdbuf[1 + sizeof(uint32_t)];
520         uint8_t *wptr = cmdbuf;
521
522         *wptr++ = PERFMON_CMD_COUNTER_CLOSE;
523         wptr = put_le_u32(wptr, ped);
524
525         xpwrite(perf_fd, cmdbuf, wptr - cmdbuf, 0);
526 }
527
528 struct perf_context *perf_create_context(struct perf_context_config *cfg)
529 {
530         struct perf_context *pctx = xzmalloc(sizeof(struct perf_context));
531
532         pctx->cfg = cfg;
533         pctx->perf_fd = xopen(cfg->perf_file, O_RDWR, 0);
534         /* perf record needs kpctl_fd, but other perf subcommands might not.  We'll
535          * delay the opening of kpctl until we need it, since kprof is picky about
536          * multiple users of kpctl. */
537         pctx->kpctl_fd = -1;
538         perf_get_arch_info(pctx->perf_fd, &pctx->pai);
539
540         return pctx;
541 }
542
543 void perf_free_context(struct perf_context *pctx)
544 {
545         if (pctx->kpctl_fd != -1)
546                 close(pctx->kpctl_fd);  /* disabled sampling */
547         close(pctx->perf_fd);   /* closes all events */
548         free(pctx);
549 }
550
551 void perf_context_event_submit(struct perf_context *pctx,
552                                                            const struct core_set *cores,
553                                                            const struct perf_eventsel *sel)
554 {
555         struct perf_event *pevt = pctx->events + pctx->event_count;
556
557         if (pctx->event_count >= COUNT_OF(pctx->events)) {
558                 fprintf(stderr, "Too many open events: %d\n", pctx->event_count);
559                 exit(1);
560         }
561         pctx->event_count++;
562         pevt->cores = *cores;
563         pevt->sel = *sel;
564         pevt->ped = perf_open_event(pctx->perf_fd, cores, sel);
565         if (pevt->ped < 0) {
566                 fprintf(stderr, "Unable to submit event \"%s\": %s\n", sel->fq_str,
567                         errstr());
568                 exit(1);
569         }
570 }
571
572 void perf_stop_events(struct perf_context *pctx)
573 {
574         for (int i = 0; i < pctx->event_count; i++)
575                 perf_close_event(pctx->perf_fd, pctx->events[i].ped);
576 }
577
578 static void ensure_kpctl_is_open(struct perf_context *pctx)
579 {
580         if (pctx->kpctl_fd == -1)
581                 pctx->kpctl_fd = xopen(pctx->cfg->kpctl_file, O_RDWR, 0);
582 }
583
584 void perf_start_sampling(struct perf_context *pctx)
585 {
586         static const char * const enable_str = "start";
587
588         ensure_kpctl_is_open(pctx);
589         xwrite(pctx->kpctl_fd, enable_str, strlen(enable_str));
590 }
591
592 void perf_stop_sampling(struct perf_context *pctx)
593 {
594         static const char * const disable_str = "stop";
595
596         ensure_kpctl_is_open(pctx);
597         xwrite(pctx->kpctl_fd, disable_str, strlen(disable_str));
598 }
599
600 void perf_context_show_events(struct perf_context *pctx, FILE *file)
601 {
602         struct perf_eventsel *sel;
603
604         for (int i = 0; i < pctx->event_count; i++) {
605                 sel = &pctx->events[i].sel;
606                 fprintf(file, "Event: %s, final code %p%s, trigger count %d\n",
607                         sel->fq_str, sel->ev.event,
608                         perfmon_is_fixed_event(&sel->ev) ? " (fixed)" : "",
609                         sel->ev.trigger_count);
610         }
611 }
612
613 static void perf_print_event_flags(const pfm_event_info_t *info, FILE *file)
614 {
615         int n = 0;
616
617         if (info->is_precise) {
618                 fputs("[precise] ", file);
619                 n++;
620         }
621         if (!n)
622                 fputs("None", file);
623 }
624
625 static void perf_print_attr_flags(const pfm_event_attr_info_t *info, FILE *file)
626 {
627         int n = 0;
628
629         if (info->is_dfl) {
630                 fputs("[default] ", file);
631                 n++;
632         }
633         if (info->is_precise) {
634                 fputs("[precise] ", file);
635                 n++;
636         }
637         if (!n)
638                 fputs("None ", file);
639 }
640
641 /* Ported from libpfm4 */
642 static void perf_show_event_info(const pfm_event_info_t *info,
643                                                                  const pfm_pmu_info_t *pinfo, FILE *file)
644 {
645         static const char * const srcs[PFM_ATTR_CTRL_MAX] = {
646                 [PFM_ATTR_CTRL_UNKNOWN] = "???",
647                 [PFM_ATTR_CTRL_PMU] = "PMU",
648                 [PFM_ATTR_CTRL_PERF_EVENT] = "perf_event",
649         };
650         pfm_event_attr_info_t ainfo;
651         int i, mod = 0, um = 0;
652
653         fprintf(file, "#-----------------------------\n"
654                         "IDX      : %d\n"
655                         "PMU name : %s (%s)\n"
656                         "Name     : %s\n"
657                         "Equiv    : %s\n",
658                         info->idx, pinfo->name, pinfo->desc,
659                         info->name, info->equiv ? info->equiv : "None");
660
661         fprintf(file, "Flags    : ");
662         perf_print_event_flags(info, file);
663         fputc('\n', file);
664
665         fprintf(file, "Desc     : %s\n", info->desc ? info->desc :
666                         "no description available");
667         fprintf(file, "Code     : 0x%"PRIx64"\n", info->code);
668
669         ZERO_DATA(ainfo);
670         ainfo.size = sizeof(ainfo);
671
672         pfm_for_each_event_attr(i, info) {
673                 const char *src;
674                 pfm_err_t err = pfm_get_event_attr_info(info->idx, i, PFM_OS_NONE,
675                                                                                                 &ainfo);
676
677                 if (err != PFM_SUCCESS) {
678                         fprintf(stderr, "Failed to get attribute info: %s\n",
679                                         pfm_strerror(err));
680                         exit(1);
681                 }
682
683                 if (ainfo.ctrl >= PFM_ATTR_CTRL_MAX) {
684                         fprintf(stderr, "event: %s has unsupported attribute source %d",
685                                         info->name, ainfo.ctrl);
686                         ainfo.ctrl = PFM_ATTR_CTRL_UNKNOWN;
687                 }
688                 src = srcs[ainfo.ctrl];
689                 switch (ainfo.type) {
690                         case PFM_ATTR_UMASK:
691                                 fprintf(file, "Umask-%02u : 0x%02"PRIx64" : %s : [%s] : ",
692                                                 um, ainfo.code, src, ainfo.name);
693                                 perf_print_attr_flags(&ainfo, file);
694                                 fputc(':', file);
695                                 if (ainfo.equiv)
696                                         fprintf(file, " Alias to %s", ainfo.equiv);
697                                 else
698                                         fprintf(file, " %s", ainfo.desc);
699                                 fputc('\n', file);
700                                 um++;
701                                 break;
702                         case PFM_ATTR_MOD_BOOL:
703                                 fprintf(file, "Modif-%02u : 0x%02"PRIx64" : %s : [%s] : "
704                                                 "%s (boolean)\n", mod, ainfo.code, src, ainfo.name,
705                                                 ainfo.desc);
706                                 mod++;
707                                 break;
708                         case PFM_ATTR_MOD_INTEGER:
709                                 fprintf(file, "Modif-%02u : 0x%02"PRIx64" : %s : [%s] : "
710                                                 "%s (integer)\n", mod, ainfo.code, src, ainfo.name,
711                                                 ainfo.desc);
712                                 mod++;
713                                 break;
714                         default:
715                                 fprintf(file, "Attr-%02u  : 0x%02"PRIx64" : %s : [%s] : %s\n",
716                                                 i, ainfo.code, ainfo.name, src, ainfo.desc);
717                 }
718         }
719 }
720
721 void perf_show_events(const char *rx, FILE *file)
722 {
723         int pmu;
724         regex_t crx;
725         pfm_pmu_info_t pinfo;
726         pfm_event_info_t info;
727         char fullname[256];
728
729         if (rx && regcomp(&crx, rx, REG_ICASE)) {
730                 fprintf(stderr, "Failed to compile event regex: '%s'\n", rx);
731                 exit(1);
732         }
733
734     ZERO_DATA(pinfo);
735     pinfo.size = sizeof(pinfo);
736     ZERO_DATA(info);
737     info.size = sizeof(info);
738
739         pfm_for_all_pmus(pmu) {
740                 pfm_err_t err = pfm_get_pmu_info(pmu, &pinfo);
741
742                 if (err != PFM_SUCCESS || !pinfo.is_present)
743                         continue;
744
745                 for (int i = pinfo.first_event; i != -1; i = pfm_get_event_next(i)) {
746                         err = pfm_get_event_info(i, PFM_OS_NONE, &info);
747                         if (err != PFM_SUCCESS) {
748                                 fprintf(stderr, "Failed to get event info: %s\n",
749                                                 pfm_strerror(err));
750                                 exit(1);
751                         }
752                         snprintf(fullname, sizeof(fullname), "%s::%s", pinfo.name,
753                                          info.name);
754                         if (!rx || regexec(&crx, fullname, 0, NULL, 0) == 0)
755                                 perf_show_event_info(&info, &pinfo, file);
756                 }
757         }
758         if (rx)
759                 regfree(&crx);
760 }
761
762 void perf_convert_trace_data(struct perfconv_context *cctx, const char *input,
763                                                          FILE *outfile)
764 {
765         FILE *infile;
766         size_t ksize;
767
768         infile = xfopen(input, "rb");
769         if (xfsize(infile) > 0) {
770                 perfconv_add_kernel_mmap(cctx);
771                 perfconv_add_kernel_buildid(cctx);
772                 perfconv_process_input(cctx, infile, outfile);
773         }
774         fclose(infile);
775 }