]> nv-tegra.nvidia Code Review - linux-3.10.git/blob - tools/perf/util/evsel.c
perf test: Add round trip test for sw and hw event names
[linux-3.10.git] / tools / perf / util / evsel.c
1 /*
2  * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
3  *
4  * Parts came from builtin-{top,stat,record}.c, see those files for further
5  * copyright notes.
6  *
7  * Released under the GPL v2. (and only v2, not any later version)
8  */
9
10 #include <byteswap.h>
11 #include <linux/bitops.h>
12 #include "asm/bug.h"
13 #include "evsel.h"
14 #include "evlist.h"
15 #include "util.h"
16 #include "cpumap.h"
17 #include "thread_map.h"
18 #include "target.h"
19 #include "../../../include/linux/hw_breakpoint.h"
20 #include "../../include/linux/perf_event.h"
21 #include "perf_regs.h"
22
23 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
24
25 static int __perf_evsel__sample_size(u64 sample_type)
26 {
27         u64 mask = sample_type & PERF_SAMPLE_MASK;
28         int size = 0;
29         int i;
30
31         for (i = 0; i < 64; i++) {
32                 if (mask & (1ULL << i))
33                         size++;
34         }
35
36         size *= sizeof(u64);
37
38         return size;
39 }
40
41 void hists__init(struct hists *hists)
42 {
43         memset(hists, 0, sizeof(*hists));
44         hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT;
45         hists->entries_in = &hists->entries_in_array[0];
46         hists->entries_collapsed = RB_ROOT;
47         hists->entries = RB_ROOT;
48         pthread_mutex_init(&hists->lock, NULL);
49 }
50
51 void perf_evsel__init(struct perf_evsel *evsel,
52                       struct perf_event_attr *attr, int idx)
53 {
54         evsel->idx         = idx;
55         evsel->attr        = *attr;
56         INIT_LIST_HEAD(&evsel->node);
57         hists__init(&evsel->hists);
58         evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
59 }
60
61 struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
62 {
63         struct perf_evsel *evsel = zalloc(sizeof(*evsel));
64
65         if (evsel != NULL)
66                 perf_evsel__init(evsel, attr, idx);
67
68         return evsel;
69 }
70
71 const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = {
72         "cycles",
73         "instructions",
74         "cache-references",
75         "cache-misses",
76         "branches",
77         "branch-misses",
78         "bus-cycles",
79         "stalled-cycles-frontend",
80         "stalled-cycles-backend",
81         "ref-cycles",
82 };
83
84 static const char *__perf_evsel__hw_name(u64 config)
85 {
86         if (config < PERF_COUNT_HW_MAX && perf_evsel__hw_names[config])
87                 return perf_evsel__hw_names[config];
88
89         return "unknown-hardware";
90 }
91
92 static int perf_evsel__add_modifiers(struct perf_evsel *evsel, char *bf, size_t size)
93 {
94         int colon = 0, r = 0;
95         struct perf_event_attr *attr = &evsel->attr;
96         bool exclude_guest_default = false;
97
98 #define MOD_PRINT(context, mod) do {                                    \
99                 if (!attr->exclude_##context) {                         \
100                         if (!colon) colon = ++r;                        \
101                         r += scnprintf(bf + r, size - r, "%c", mod);    \
102                 } } while(0)
103
104         if (attr->exclude_kernel || attr->exclude_user || attr->exclude_hv) {
105                 MOD_PRINT(kernel, 'k');
106                 MOD_PRINT(user, 'u');
107                 MOD_PRINT(hv, 'h');
108                 exclude_guest_default = true;
109         }
110
111         if (attr->precise_ip) {
112                 if (!colon)
113                         colon = ++r;
114                 r += scnprintf(bf + r, size - r, "%.*s", attr->precise_ip, "ppp");
115                 exclude_guest_default = true;
116         }
117
118         if (attr->exclude_host || attr->exclude_guest == exclude_guest_default) {
119                 MOD_PRINT(host, 'H');
120                 MOD_PRINT(guest, 'G');
121         }
122 #undef MOD_PRINT
123         if (colon)
124                 bf[colon - 1] = ':';
125         return r;
126 }
127
128 static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
129 {
130         int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(evsel->attr.config));
131         return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
132 }
133
134 const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX] = {
135         "cpu-clock",
136         "task-clock",
137         "page-faults",
138         "context-switches",
139         "cpu-migrations",
140         "minor-faults",
141         "major-faults",
142         "alignment-faults",
143         "emulation-faults",
144 };
145
146 static const char *__perf_evsel__sw_name(u64 config)
147 {
148         if (config < PERF_COUNT_SW_MAX && perf_evsel__sw_names[config])
149                 return perf_evsel__sw_names[config];
150         return "unknown-software";
151 }
152
153 static int perf_evsel__sw_name(struct perf_evsel *evsel, char *bf, size_t size)
154 {
155         int r = scnprintf(bf, size, "%s", __perf_evsel__sw_name(evsel->attr.config));
156         return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
157 }
158
159 static int __perf_evsel__bp_name(char *bf, size_t size, u64 addr, u64 type)
160 {
161         int r;
162
163         r = scnprintf(bf, size, "mem:0x%" PRIx64 ":", addr);
164
165         if (type & HW_BREAKPOINT_R)
166                 r += scnprintf(bf + r, size - r, "r");
167
168         if (type & HW_BREAKPOINT_W)
169                 r += scnprintf(bf + r, size - r, "w");
170
171         if (type & HW_BREAKPOINT_X)
172                 r += scnprintf(bf + r, size - r, "x");
173
174         return r;
175 }
176
177 static int perf_evsel__bp_name(struct perf_evsel *evsel, char *bf, size_t size)
178 {
179         struct perf_event_attr *attr = &evsel->attr;
180         int r = __perf_evsel__bp_name(bf, size, attr->bp_addr, attr->bp_type);
181         return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
182 }
183
184 const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX]
185                                 [PERF_EVSEL__MAX_ALIASES] = {
186  { "L1-dcache", "l1-d",         "l1d",          "L1-data",              },
187  { "L1-icache", "l1-i",         "l1i",          "L1-instruction",       },
188  { "LLC",       "L2",                                                   },
189  { "dTLB",      "d-tlb",        "Data-TLB",                             },
190  { "iTLB",      "i-tlb",        "Instruction-TLB",                      },
191  { "branch",    "branches",     "bpu",          "btb",          "bpc",  },
192  { "node",                                                              },
193 };
194
195 const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX]
196                                    [PERF_EVSEL__MAX_ALIASES] = {
197  { "load",      "loads",        "read",                                 },
198  { "store",     "stores",       "write",                                },
199  { "prefetch",  "prefetches",   "speculative-read", "speculative-load", },
200 };
201
202 const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
203                                        [PERF_EVSEL__MAX_ALIASES] = {
204  { "refs",      "Reference",    "ops",          "access",               },
205  { "misses",    "miss",                                                 },
206 };
207
208 #define C(x)            PERF_COUNT_HW_CACHE_##x
209 #define CACHE_READ      (1 << C(OP_READ))
210 #define CACHE_WRITE     (1 << C(OP_WRITE))
211 #define CACHE_PREFETCH  (1 << C(OP_PREFETCH))
212 #define COP(x)          (1 << x)
213
214 /*
215  * cache operartion stat
216  * L1I : Read and prefetch only
217  * ITLB and BPU : Read-only
218  */
219 static unsigned long perf_evsel__hw_cache_stat[C(MAX)] = {
220  [C(L1D)]       = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
221  [C(L1I)]       = (CACHE_READ | CACHE_PREFETCH),
222  [C(LL)]        = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
223  [C(DTLB)]      = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
224  [C(ITLB)]      = (CACHE_READ),
225  [C(BPU)]       = (CACHE_READ),
226  [C(NODE)]      = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
227 };
228
229 bool perf_evsel__is_cache_op_valid(u8 type, u8 op)
230 {
231         if (perf_evsel__hw_cache_stat[type] & COP(op))
232                 return true;    /* valid */
233         else
234                 return false;   /* invalid */
235 }
236
237 int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
238                                             char *bf, size_t size)
239 {
240         if (result) {
241                 return scnprintf(bf, size, "%s-%s-%s", perf_evsel__hw_cache[type][0],
242                                  perf_evsel__hw_cache_op[op][0],
243                                  perf_evsel__hw_cache_result[result][0]);
244         }
245
246         return scnprintf(bf, size, "%s-%s", perf_evsel__hw_cache[type][0],
247                          perf_evsel__hw_cache_op[op][1]);
248 }
249
250 static int __perf_evsel__hw_cache_name(u64 config, char *bf, size_t size)
251 {
252         u8 op, result, type = (config >>  0) & 0xff;
253         const char *err = "unknown-ext-hardware-cache-type";
254
255         if (type > PERF_COUNT_HW_CACHE_MAX)
256                 goto out_err;
257
258         op = (config >>  8) & 0xff;
259         err = "unknown-ext-hardware-cache-op";
260         if (op > PERF_COUNT_HW_CACHE_OP_MAX)
261                 goto out_err;
262
263         result = (config >> 16) & 0xff;
264         err = "unknown-ext-hardware-cache-result";
265         if (result > PERF_COUNT_HW_CACHE_RESULT_MAX)
266                 goto out_err;
267
268         err = "invalid-cache";
269         if (!perf_evsel__is_cache_op_valid(type, op))
270                 goto out_err;
271
272         return __perf_evsel__hw_cache_type_op_res_name(type, op, result, bf, size);
273 out_err:
274         return scnprintf(bf, size, "%s", err);
275 }
276
277 static int perf_evsel__hw_cache_name(struct perf_evsel *evsel, char *bf, size_t size)
278 {
279         int ret = __perf_evsel__hw_cache_name(evsel->attr.config, bf, size);
280         return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
281 }
282
283 static int perf_evsel__raw_name(struct perf_evsel *evsel, char *bf, size_t size)
284 {
285         int ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config);
286         return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
287 }
288
289 const char *perf_evsel__name(struct perf_evsel *evsel)
290 {
291         char bf[128];
292
293         if (evsel->name)
294                 return evsel->name;
295
296         switch (evsel->attr.type) {
297         case PERF_TYPE_RAW:
298                 perf_evsel__raw_name(evsel, bf, sizeof(bf));
299                 break;
300
301         case PERF_TYPE_HARDWARE:
302                 perf_evsel__hw_name(evsel, bf, sizeof(bf));
303                 break;
304
305         case PERF_TYPE_HW_CACHE:
306                 perf_evsel__hw_cache_name(evsel, bf, sizeof(bf));
307                 break;
308
309         case PERF_TYPE_SOFTWARE:
310                 perf_evsel__sw_name(evsel, bf, sizeof(bf));
311                 break;
312
313         case PERF_TYPE_TRACEPOINT:
314                 scnprintf(bf, sizeof(bf), "%s", "unknown tracepoint");
315                 break;
316
317         case PERF_TYPE_BREAKPOINT:
318                 perf_evsel__bp_name(evsel, bf, sizeof(bf));
319                 break;
320
321         default:
322                 scnprintf(bf, sizeof(bf), "unknown attr type: %d",
323                           evsel->attr.type);
324                 break;
325         }
326
327         evsel->name = strdup(bf);
328
329         return evsel->name ?: "unknown";
330 }
331
332 void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
333                         struct perf_evsel *first)
334 {
335         struct perf_event_attr *attr = &evsel->attr;
336         int track = !evsel->idx; /* only the first counter needs these */
337
338         attr->disabled = 1;
339         attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
340         attr->inherit       = !opts->no_inherit;
341         attr->read_format   = PERF_FORMAT_TOTAL_TIME_ENABLED |
342                               PERF_FORMAT_TOTAL_TIME_RUNNING |
343                               PERF_FORMAT_ID;
344
345         attr->sample_type  |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
346
347         /*
348          * We default some events to a 1 default interval. But keep
349          * it a weak assumption overridable by the user.
350          */
351         if (!attr->sample_period || (opts->user_freq != UINT_MAX &&
352                                      opts->user_interval != ULLONG_MAX)) {
353                 if (opts->freq) {
354                         attr->sample_type       |= PERF_SAMPLE_PERIOD;
355                         attr->freq              = 1;
356                         attr->sample_freq       = opts->freq;
357                 } else {
358                         attr->sample_period = opts->default_interval;
359                 }
360         }
361
362         if (opts->no_samples)
363                 attr->sample_freq = 0;
364
365         if (opts->inherit_stat)
366                 attr->inherit_stat = 1;
367
368         if (opts->sample_address) {
369                 attr->sample_type       |= PERF_SAMPLE_ADDR;
370                 attr->mmap_data = track;
371         }
372
373         if (opts->call_graph) {
374                 attr->sample_type       |= PERF_SAMPLE_CALLCHAIN;
375
376                 if (opts->call_graph == CALLCHAIN_DWARF) {
377                         attr->sample_type |= PERF_SAMPLE_REGS_USER |
378                                              PERF_SAMPLE_STACK_USER;
379                         attr->sample_regs_user = PERF_REGS_MASK;
380                         attr->sample_stack_user = opts->stack_dump_size;
381                         attr->exclude_callchain_user = 1;
382                 }
383         }
384
385         if (perf_target__has_cpu(&opts->target))
386                 attr->sample_type       |= PERF_SAMPLE_CPU;
387
388         if (opts->period)
389                 attr->sample_type       |= PERF_SAMPLE_PERIOD;
390
391         if (!opts->sample_id_all_missing &&
392             (opts->sample_time || !opts->no_inherit ||
393              perf_target__has_cpu(&opts->target)))
394                 attr->sample_type       |= PERF_SAMPLE_TIME;
395
396         if (opts->raw_samples) {
397                 attr->sample_type       |= PERF_SAMPLE_TIME;
398                 attr->sample_type       |= PERF_SAMPLE_RAW;
399                 attr->sample_type       |= PERF_SAMPLE_CPU;
400         }
401
402         if (opts->no_delay) {
403                 attr->watermark = 0;
404                 attr->wakeup_events = 1;
405         }
406         if (opts->branch_stack) {
407                 attr->sample_type       |= PERF_SAMPLE_BRANCH_STACK;
408                 attr->branch_sample_type = opts->branch_stack;
409         }
410
411         attr->mmap = track;
412         attr->comm = track;
413
414         if (perf_target__none(&opts->target) &&
415             (!opts->group || evsel == first)) {
416                 attr->enable_on_exec = 1;
417         }
418 }
419
420 int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
421 {
422         int cpu, thread;
423         evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int));
424
425         if (evsel->fd) {
426                 for (cpu = 0; cpu < ncpus; cpu++) {
427                         for (thread = 0; thread < nthreads; thread++) {
428                                 FD(evsel, cpu, thread) = -1;
429                         }
430                 }
431         }
432
433         return evsel->fd != NULL ? 0 : -ENOMEM;
434 }
435
436 int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
437 {
438         evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id));
439         if (evsel->sample_id == NULL)
440                 return -ENOMEM;
441
442         evsel->id = zalloc(ncpus * nthreads * sizeof(u64));
443         if (evsel->id == NULL) {
444                 xyarray__delete(evsel->sample_id);
445                 evsel->sample_id = NULL;
446                 return -ENOMEM;
447         }
448
449         return 0;
450 }
451
452 int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
453 {
454         evsel->counts = zalloc((sizeof(*evsel->counts) +
455                                 (ncpus * sizeof(struct perf_counts_values))));
456         return evsel->counts != NULL ? 0 : -ENOMEM;
457 }
458
459 void perf_evsel__free_fd(struct perf_evsel *evsel)
460 {
461         xyarray__delete(evsel->fd);
462         evsel->fd = NULL;
463 }
464
465 void perf_evsel__free_id(struct perf_evsel *evsel)
466 {
467         xyarray__delete(evsel->sample_id);
468         evsel->sample_id = NULL;
469         free(evsel->id);
470         evsel->id = NULL;
471 }
472
473 void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
474 {
475         int cpu, thread;
476
477         for (cpu = 0; cpu < ncpus; cpu++)
478                 for (thread = 0; thread < nthreads; ++thread) {
479                         close(FD(evsel, cpu, thread));
480                         FD(evsel, cpu, thread) = -1;
481                 }
482 }
483
484 void perf_evsel__exit(struct perf_evsel *evsel)
485 {
486         assert(list_empty(&evsel->node));
487         xyarray__delete(evsel->fd);
488         xyarray__delete(evsel->sample_id);
489         free(evsel->id);
490 }
491
492 void perf_evsel__delete(struct perf_evsel *evsel)
493 {
494         perf_evsel__exit(evsel);
495         close_cgroup(evsel->cgrp);
496         free(evsel->group_name);
497         free(evsel->name);
498         free(evsel);
499 }
500
501 int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
502                               int cpu, int thread, bool scale)
503 {
504         struct perf_counts_values count;
505         size_t nv = scale ? 3 : 1;
506
507         if (FD(evsel, cpu, thread) < 0)
508                 return -EINVAL;
509
510         if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1) < 0)
511                 return -ENOMEM;
512
513         if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0)
514                 return -errno;
515
516         if (scale) {
517                 if (count.run == 0)
518                         count.val = 0;
519                 else if (count.run < count.ena)
520                         count.val = (u64)((double)count.val * count.ena / count.run + 0.5);
521         } else
522                 count.ena = count.run = 0;
523
524         evsel->counts->cpu[cpu] = count;
525         return 0;
526 }
527
528 int __perf_evsel__read(struct perf_evsel *evsel,
529                        int ncpus, int nthreads, bool scale)
530 {
531         size_t nv = scale ? 3 : 1;
532         int cpu, thread;
533         struct perf_counts_values *aggr = &evsel->counts->aggr, count;
534
535         aggr->val = aggr->ena = aggr->run = 0;
536
537         for (cpu = 0; cpu < ncpus; cpu++) {
538                 for (thread = 0; thread < nthreads; thread++) {
539                         if (FD(evsel, cpu, thread) < 0)
540                                 continue;
541
542                         if (readn(FD(evsel, cpu, thread),
543                                   &count, nv * sizeof(u64)) < 0)
544                                 return -errno;
545
546                         aggr->val += count.val;
547                         if (scale) {
548                                 aggr->ena += count.ena;
549                                 aggr->run += count.run;
550                         }
551                 }
552         }
553
554         evsel->counts->scaled = 0;
555         if (scale) {
556                 if (aggr->run == 0) {
557                         evsel->counts->scaled = -1;
558                         aggr->val = 0;
559                         return 0;
560                 }
561
562                 if (aggr->run < aggr->ena) {
563                         evsel->counts->scaled = 1;
564                         aggr->val = (u64)((double)aggr->val * aggr->ena / aggr->run + 0.5);
565                 }
566         } else
567                 aggr->ena = aggr->run = 0;
568
569         return 0;
570 }
571
572 static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread)
573 {
574         struct perf_evsel *leader = evsel->leader;
575         int fd;
576
577         if (!leader)
578                 return -1;
579
580         /*
581          * Leader must be already processed/open,
582          * if not it's a bug.
583          */
584         BUG_ON(!leader->fd);
585
586         fd = FD(leader, cpu, thread);
587         BUG_ON(fd == -1);
588
589         return fd;
590 }
591
592 static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
593                               struct thread_map *threads)
594 {
595         int cpu, thread;
596         unsigned long flags = 0;
597         int pid = -1, err;
598
599         if (evsel->fd == NULL &&
600             perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0)
601                 return -ENOMEM;
602
603         if (evsel->cgrp) {
604                 flags = PERF_FLAG_PID_CGROUP;
605                 pid = evsel->cgrp->fd;
606         }
607
608         for (cpu = 0; cpu < cpus->nr; cpu++) {
609
610                 for (thread = 0; thread < threads->nr; thread++) {
611                         int group_fd;
612
613                         if (!evsel->cgrp)
614                                 pid = threads->map[thread];
615
616                         group_fd = get_group_fd(evsel, cpu, thread);
617
618                         FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr,
619                                                                      pid,
620                                                                      cpus->map[cpu],
621                                                                      group_fd, flags);
622                         if (FD(evsel, cpu, thread) < 0) {
623                                 err = -errno;
624                                 goto out_close;
625                         }
626                 }
627         }
628
629         return 0;
630
631 out_close:
632         do {
633                 while (--thread >= 0) {
634                         close(FD(evsel, cpu, thread));
635                         FD(evsel, cpu, thread) = -1;
636                 }
637                 thread = threads->nr;
638         } while (--cpu >= 0);
639         return err;
640 }
641
642 void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads)
643 {
644         if (evsel->fd == NULL)
645                 return;
646
647         perf_evsel__close_fd(evsel, ncpus, nthreads);
648         perf_evsel__free_fd(evsel);
649         evsel->fd = NULL;
650 }
651
652 static struct {
653         struct cpu_map map;
654         int cpus[1];
655 } empty_cpu_map = {
656         .map.nr = 1,
657         .cpus   = { -1, },
658 };
659
660 static struct {
661         struct thread_map map;
662         int threads[1];
663 } empty_thread_map = {
664         .map.nr  = 1,
665         .threads = { -1, },
666 };
667
668 int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
669                      struct thread_map *threads)
670 {
671         if (cpus == NULL) {
672                 /* Work around old compiler warnings about strict aliasing */
673                 cpus = &empty_cpu_map.map;
674         }
675
676         if (threads == NULL)
677                 threads = &empty_thread_map.map;
678
679         return __perf_evsel__open(evsel, cpus, threads);
680 }
681
682 int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
683                              struct cpu_map *cpus)
684 {
685         return __perf_evsel__open(evsel, cpus, &empty_thread_map.map);
686 }
687
688 int perf_evsel__open_per_thread(struct perf_evsel *evsel,
689                                 struct thread_map *threads)
690 {
691         return __perf_evsel__open(evsel, &empty_cpu_map.map, threads);
692 }
693
694 static int perf_event__parse_id_sample(const union perf_event *event, u64 type,
695                                        struct perf_sample *sample,
696                                        bool swapped)
697 {
698         const u64 *array = event->sample.array;
699         union u64_swap u;
700
701         array += ((event->header.size -
702                    sizeof(event->header)) / sizeof(u64)) - 1;
703
704         if (type & PERF_SAMPLE_CPU) {
705                 u.val64 = *array;
706                 if (swapped) {
707                         /* undo swap of u64, then swap on individual u32s */
708                         u.val64 = bswap_64(u.val64);
709                         u.val32[0] = bswap_32(u.val32[0]);
710                 }
711
712                 sample->cpu = u.val32[0];
713                 array--;
714         }
715
716         if (type & PERF_SAMPLE_STREAM_ID) {
717                 sample->stream_id = *array;
718                 array--;
719         }
720
721         if (type & PERF_SAMPLE_ID) {
722                 sample->id = *array;
723                 array--;
724         }
725
726         if (type & PERF_SAMPLE_TIME) {
727                 sample->time = *array;
728                 array--;
729         }
730
731         if (type & PERF_SAMPLE_TID) {
732                 u.val64 = *array;
733                 if (swapped) {
734                         /* undo swap of u64, then swap on individual u32s */
735                         u.val64 = bswap_64(u.val64);
736                         u.val32[0] = bswap_32(u.val32[0]);
737                         u.val32[1] = bswap_32(u.val32[1]);
738                 }
739
740                 sample->pid = u.val32[0];
741                 sample->tid = u.val32[1];
742         }
743
744         return 0;
745 }
746
747 static bool sample_overlap(const union perf_event *event,
748                            const void *offset, u64 size)
749 {
750         const void *base = event;
751
752         if (offset + size > base + event->header.size)
753                 return true;
754
755         return false;
756 }
757
758 int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
759                              struct perf_sample *data, bool swapped)
760 {
761         u64 type = evsel->attr.sample_type;
762         u64 regs_user = evsel->attr.sample_regs_user;
763         const u64 *array;
764
765         /*
766          * used for cross-endian analysis. See git commit 65014ab3
767          * for why this goofiness is needed.
768          */
769         union u64_swap u;
770
771         memset(data, 0, sizeof(*data));
772         data->cpu = data->pid = data->tid = -1;
773         data->stream_id = data->id = data->time = -1ULL;
774         data->period = 1;
775
776         if (event->header.type != PERF_RECORD_SAMPLE) {
777                 if (!evsel->attr.sample_id_all)
778                         return 0;
779                 return perf_event__parse_id_sample(event, type, data, swapped);
780         }
781
782         array = event->sample.array;
783
784         if (evsel->sample_size + sizeof(event->header) > event->header.size)
785                 return -EFAULT;
786
787         if (type & PERF_SAMPLE_IP) {
788                 data->ip = event->ip.ip;
789                 array++;
790         }
791
792         if (type & PERF_SAMPLE_TID) {
793                 u.val64 = *array;
794                 if (swapped) {
795                         /* undo swap of u64, then swap on individual u32s */
796                         u.val64 = bswap_64(u.val64);
797                         u.val32[0] = bswap_32(u.val32[0]);
798                         u.val32[1] = bswap_32(u.val32[1]);
799                 }
800
801                 data->pid = u.val32[0];
802                 data->tid = u.val32[1];
803                 array++;
804         }
805
806         if (type & PERF_SAMPLE_TIME) {
807                 data->time = *array;
808                 array++;
809         }
810
811         data->addr = 0;
812         if (type & PERF_SAMPLE_ADDR) {
813                 data->addr = *array;
814                 array++;
815         }
816
817         data->id = -1ULL;
818         if (type & PERF_SAMPLE_ID) {
819                 data->id = *array;
820                 array++;
821         }
822
823         if (type & PERF_SAMPLE_STREAM_ID) {
824                 data->stream_id = *array;
825                 array++;
826         }
827
828         if (type & PERF_SAMPLE_CPU) {
829
830                 u.val64 = *array;
831                 if (swapped) {
832                         /* undo swap of u64, then swap on individual u32s */
833                         u.val64 = bswap_64(u.val64);
834                         u.val32[0] = bswap_32(u.val32[0]);
835                 }
836
837                 data->cpu = u.val32[0];
838                 array++;
839         }
840
841         if (type & PERF_SAMPLE_PERIOD) {
842                 data->period = *array;
843                 array++;
844         }
845
846         if (type & PERF_SAMPLE_READ) {
847                 fprintf(stderr, "PERF_SAMPLE_READ is unsupported for now\n");
848                 return -1;
849         }
850
851         if (type & PERF_SAMPLE_CALLCHAIN) {
852                 if (sample_overlap(event, array, sizeof(data->callchain->nr)))
853                         return -EFAULT;
854
855                 data->callchain = (struct ip_callchain *)array;
856
857                 if (sample_overlap(event, array, data->callchain->nr))
858                         return -EFAULT;
859
860                 array += 1 + data->callchain->nr;
861         }
862
863         if (type & PERF_SAMPLE_RAW) {
864                 const u64 *pdata;
865
866                 u.val64 = *array;
867                 if (WARN_ONCE(swapped,
868                               "Endianness of raw data not corrected!\n")) {
869                         /* undo swap of u64, then swap on individual u32s */
870                         u.val64 = bswap_64(u.val64);
871                         u.val32[0] = bswap_32(u.val32[0]);
872                         u.val32[1] = bswap_32(u.val32[1]);
873                 }
874
875                 if (sample_overlap(event, array, sizeof(u32)))
876                         return -EFAULT;
877
878                 data->raw_size = u.val32[0];
879                 pdata = (void *) array + sizeof(u32);
880
881                 if (sample_overlap(event, pdata, data->raw_size))
882                         return -EFAULT;
883
884                 data->raw_data = (void *) pdata;
885
886                 array = (void *)array + data->raw_size + sizeof(u32);
887         }
888
889         if (type & PERF_SAMPLE_BRANCH_STACK) {
890                 u64 sz;
891
892                 data->branch_stack = (struct branch_stack *)array;
893                 array++; /* nr */
894
895                 sz = data->branch_stack->nr * sizeof(struct branch_entry);
896                 sz /= sizeof(u64);
897                 array += sz;
898         }
899
900         if (type & PERF_SAMPLE_REGS_USER) {
901                 /* First u64 tells us if we have any regs in sample. */
902                 u64 avail = *array++;
903
904                 if (avail) {
905                         data->user_regs.regs = (u64 *)array;
906                         array += hweight_long(regs_user);
907                 }
908         }
909
910         if (type & PERF_SAMPLE_STACK_USER) {
911                 u64 size = *array++;
912
913                 data->user_stack.offset = ((char *)(array - 1)
914                                           - (char *) event);
915
916                 if (!size) {
917                         data->user_stack.size = 0;
918                 } else {
919                         data->user_stack.data = (char *)array;
920                         array += size / sizeof(*array);
921                         data->user_stack.size = *array;
922                 }
923         }
924
925         return 0;
926 }
927
928 int perf_event__synthesize_sample(union perf_event *event, u64 type,
929                                   const struct perf_sample *sample,
930                                   bool swapped)
931 {
932         u64 *array;
933
934         /*
935          * used for cross-endian analysis. See git commit 65014ab3
936          * for why this goofiness is needed.
937          */
938         union u64_swap u;
939
940         array = event->sample.array;
941
942         if (type & PERF_SAMPLE_IP) {
943                 event->ip.ip = sample->ip;
944                 array++;
945         }
946
947         if (type & PERF_SAMPLE_TID) {
948                 u.val32[0] = sample->pid;
949                 u.val32[1] = sample->tid;
950                 if (swapped) {
951                         /*
952                          * Inverse of what is done in perf_evsel__parse_sample
953                          */
954                         u.val32[0] = bswap_32(u.val32[0]);
955                         u.val32[1] = bswap_32(u.val32[1]);
956                         u.val64 = bswap_64(u.val64);
957                 }
958
959                 *array = u.val64;
960                 array++;
961         }
962
963         if (type & PERF_SAMPLE_TIME) {
964                 *array = sample->time;
965                 array++;
966         }
967
968         if (type & PERF_SAMPLE_ADDR) {
969                 *array = sample->addr;
970                 array++;
971         }
972
973         if (type & PERF_SAMPLE_ID) {
974                 *array = sample->id;
975                 array++;
976         }
977
978         if (type & PERF_SAMPLE_STREAM_ID) {
979                 *array = sample->stream_id;
980                 array++;
981         }
982
983         if (type & PERF_SAMPLE_CPU) {
984                 u.val32[0] = sample->cpu;
985                 if (swapped) {
986                         /*
987                          * Inverse of what is done in perf_evsel__parse_sample
988                          */
989                         u.val32[0] = bswap_32(u.val32[0]);
990                         u.val64 = bswap_64(u.val64);
991                 }
992                 *array = u.val64;
993                 array++;
994         }
995
996         if (type & PERF_SAMPLE_PERIOD) {
997                 *array = sample->period;
998                 array++;
999         }
1000
1001         return 0;
1002 }