blob: 407095af1456058fcbea7acf62f745bc044a5437 [file] [log] [blame]
Mathieu Poirier440a23b2018-01-17 10:52:11 -07001/*
2 * SPDX-License-Identifier: GPL-2.0
3 *
4 * Copyright(C) 2015-2018 Linaro Limited.
5 *
6 * Author: Tor Jeremiassen <tor@ti.com>
7 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
8 */
9
10#include <linux/bitops.h>
11#include <linux/err.h>
12#include <linux/kernel.h>
13#include <linux/log2.h>
14#include <linux/types.h>
15
16#include <stdlib.h>
17
18#include "auxtrace.h"
19#include "color.h"
20#include "cs-etm.h"
Mathieu Poirier68ffe392018-01-17 10:52:13 -070021#include "cs-etm-decoder/cs-etm-decoder.h"
Mathieu Poirier440a23b2018-01-17 10:52:11 -070022#include "debug.h"
23#include "evlist.h"
24#include "intlist.h"
25#include "machine.h"
26#include "map.h"
27#include "perf.h"
28#include "thread.h"
29#include "thread_map.h"
30#include "thread-stack.h"
31#include "util.h"
32
33#define MAX_TIMESTAMP (~0ULL)
34
35struct cs_etm_auxtrace {
36 struct auxtrace auxtrace;
37 struct auxtrace_queues queues;
38 struct auxtrace_heap heap;
39 struct itrace_synth_opts synth_opts;
40 struct perf_session *session;
41 struct machine *machine;
42 struct thread *unknown_thread;
43
44 u8 timeless_decoding;
45 u8 snapshot_mode;
46 u8 data_queued;
47 u8 sample_branches;
48
49 int num_cpu;
50 u32 auxtrace_type;
51 u64 branches_sample_type;
52 u64 branches_id;
53 u64 **metadata;
54 u64 kernel_start;
55 unsigned int pmu_type;
56};
57
58struct cs_etm_queue {
59 struct cs_etm_auxtrace *etm;
60 struct thread *thread;
61 struct cs_etm_decoder *decoder;
62 struct auxtrace_buffer *buffer;
63 const struct cs_etm_state *state;
64 union perf_event *event_buf;
65 unsigned int queue_nr;
66 pid_t pid, tid;
67 int cpu;
68 u64 time;
69 u64 timestamp;
70 u64 offset;
71};
72
Mathieu Poirier9f878b22018-01-17 10:52:17 -070073static int cs_etm__update_queues(struct cs_etm_auxtrace *etm);
74static int cs_etm__process_timeless_queues(struct cs_etm_auxtrace *etm,
75 pid_t tid, u64 time_);
76
Mathieu Poirier68ffe392018-01-17 10:52:13 -070077static void cs_etm__packet_dump(const char *pkt_string)
78{
79 const char *color = PERF_COLOR_BLUE;
80 int len = strlen(pkt_string);
81
82 if (len && (pkt_string[len-1] == '\n'))
83 color_fprintf(stdout, color, " %s", pkt_string);
84 else
85 color_fprintf(stdout, color, " %s\n", pkt_string);
86
87 fflush(stdout);
88}
89
90static void cs_etm__dump_event(struct cs_etm_auxtrace *etm,
91 struct auxtrace_buffer *buffer)
92{
93 int i, ret;
94 const char *color = PERF_COLOR_BLUE;
95 struct cs_etm_decoder_params d_params;
96 struct cs_etm_trace_params *t_params;
97 struct cs_etm_decoder *decoder;
98 size_t buffer_used = 0;
99
100 fprintf(stdout, "\n");
101 color_fprintf(stdout, color,
102 ". ... CoreSight ETM Trace data: size %zu bytes\n",
103 buffer->size);
104
105 /* Use metadata to fill in trace parameters for trace decoder */
106 t_params = zalloc(sizeof(*t_params) * etm->num_cpu);
107 for (i = 0; i < etm->num_cpu; i++) {
108 t_params[i].protocol = CS_ETM_PROTO_ETMV4i;
109 t_params[i].etmv4.reg_idr0 = etm->metadata[i][CS_ETMV4_TRCIDR0];
110 t_params[i].etmv4.reg_idr1 = etm->metadata[i][CS_ETMV4_TRCIDR1];
111 t_params[i].etmv4.reg_idr2 = etm->metadata[i][CS_ETMV4_TRCIDR2];
112 t_params[i].etmv4.reg_idr8 = etm->metadata[i][CS_ETMV4_TRCIDR8];
113 t_params[i].etmv4.reg_configr =
114 etm->metadata[i][CS_ETMV4_TRCCONFIGR];
115 t_params[i].etmv4.reg_traceidr =
116 etm->metadata[i][CS_ETMV4_TRCTRACEIDR];
117 }
118
119 /* Set decoder parameters to simply print the trace packets */
120 d_params.packet_printer = cs_etm__packet_dump;
121 d_params.operation = CS_ETM_OPERATION_PRINT;
122 d_params.formatted = true;
123 d_params.fsyncs = false;
124 d_params.hsyncs = false;
125 d_params.frame_aligned = true;
126
127 decoder = cs_etm_decoder__new(etm->num_cpu, &d_params, t_params);
128
129 zfree(&t_params);
130
131 if (!decoder)
132 return;
133 do {
134 size_t consumed;
135
136 ret = cs_etm_decoder__process_data_block(
137 decoder, buffer->offset,
138 &((u8 *)buffer->data)[buffer_used],
139 buffer->size - buffer_used, &consumed);
140 if (ret)
141 break;
142
143 buffer_used += consumed;
144 } while (buffer_used < buffer->size);
145
146 cs_etm_decoder__free(decoder);
147}
148
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700149static int cs_etm__flush_events(struct perf_session *session,
150 struct perf_tool *tool)
151{
Mathieu Poirier9f878b22018-01-17 10:52:17 -0700152 int ret;
153 struct cs_etm_auxtrace *etm = container_of(session->auxtrace,
154 struct cs_etm_auxtrace,
155 auxtrace);
156 if (dump_trace)
157 return 0;
158
159 if (!tool->ordered_events)
160 return -EINVAL;
161
162 if (!etm->timeless_decoding)
163 return -EINVAL;
164
165 ret = cs_etm__update_queues(etm);
166
167 if (ret < 0)
168 return ret;
169
170 return cs_etm__process_timeless_queues(etm, -1, MAX_TIMESTAMP - 1);
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700171}
172
173static void cs_etm__free_queue(void *priv)
174{
175 struct cs_etm_queue *etmq = priv;
176
177 free(etmq);
178}
179
180static void cs_etm__free_events(struct perf_session *session)
181{
182 unsigned int i;
183 struct cs_etm_auxtrace *aux = container_of(session->auxtrace,
184 struct cs_etm_auxtrace,
185 auxtrace);
186 struct auxtrace_queues *queues = &aux->queues;
187
188 for (i = 0; i < queues->nr_queues; i++) {
189 cs_etm__free_queue(queues->queue_array[i].priv);
190 queues->queue_array[i].priv = NULL;
191 }
192
193 auxtrace_queues__free(queues);
194}
195
196static void cs_etm__free(struct perf_session *session)
197{
Tor Jeremiassencd8bfd82018-01-17 10:52:12 -0700198 int i;
199 struct int_node *inode, *tmp;
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700200 struct cs_etm_auxtrace *aux = container_of(session->auxtrace,
201 struct cs_etm_auxtrace,
202 auxtrace);
203 cs_etm__free_events(session);
204 session->auxtrace = NULL;
205
Tor Jeremiassencd8bfd82018-01-17 10:52:12 -0700206 /* First remove all traceID/CPU# nodes for the RB tree */
207 intlist__for_each_entry_safe(inode, tmp, traceid_list)
208 intlist__remove(traceid_list, inode);
209 /* Then the RB tree itself */
210 intlist__delete(traceid_list);
211
212 for (i = 0; i < aux->num_cpu; i++)
213 zfree(&aux->metadata[i]);
214
215 zfree(&aux->metadata);
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700216 zfree(&aux);
217}
218
Mathieu Poirier20d9c472018-01-17 10:52:16 -0700219static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u64 address,
220 size_t size, u8 *buffer)
221{
222 u8 cpumode;
223 u64 offset;
224 int len;
225 struct thread *thread;
226 struct machine *machine;
227 struct addr_location al;
228
229 if (!etmq)
230 return -1;
231
232 machine = etmq->etm->machine;
233 if (address >= etmq->etm->kernel_start)
234 cpumode = PERF_RECORD_MISC_KERNEL;
235 else
236 cpumode = PERF_RECORD_MISC_USER;
237
238 thread = etmq->thread;
239 if (!thread) {
240 if (cpumode != PERF_RECORD_MISC_KERNEL)
241 return -EINVAL;
242 thread = etmq->etm->unknown_thread;
243 }
244
245 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, address, &al);
246
247 if (!al.map || !al.map->dso)
248 return 0;
249
250 if (al.map->dso->data.status == DSO_DATA_STATUS_ERROR &&
251 dso__data_status_seen(al.map->dso, DSO_DATA_STATUS_SEEN_ITRACE))
252 return 0;
253
254 offset = al.map->map_ip(al.map, address);
255
256 map__load(al.map);
257
258 len = dso__data_read_offset(al.map->dso, machine, offset, buffer, size);
259
260 if (len <= 0)
261 return 0;
262
263 return len;
264}
265
266static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm,
267 unsigned int queue_nr)
268{
269 int i;
270 struct cs_etm_decoder_params d_params;
271 struct cs_etm_trace_params *t_params;
272 struct cs_etm_queue *etmq;
273
274 etmq = zalloc(sizeof(*etmq));
275 if (!etmq)
276 return NULL;
277
278 etmq->event_buf = malloc(PERF_SAMPLE_MAX_SIZE);
279 if (!etmq->event_buf)
280 goto out_free;
281
282 etmq->etm = etm;
283 etmq->queue_nr = queue_nr;
284 etmq->pid = -1;
285 etmq->tid = -1;
286 etmq->cpu = -1;
287
288 /* Use metadata to fill in trace parameters for trace decoder */
289 t_params = zalloc(sizeof(*t_params) * etm->num_cpu);
290
291 if (!t_params)
292 goto out_free;
293
294 for (i = 0; i < etm->num_cpu; i++) {
295 t_params[i].protocol = CS_ETM_PROTO_ETMV4i;
296 t_params[i].etmv4.reg_idr0 = etm->metadata[i][CS_ETMV4_TRCIDR0];
297 t_params[i].etmv4.reg_idr1 = etm->metadata[i][CS_ETMV4_TRCIDR1];
298 t_params[i].etmv4.reg_idr2 = etm->metadata[i][CS_ETMV4_TRCIDR2];
299 t_params[i].etmv4.reg_idr8 = etm->metadata[i][CS_ETMV4_TRCIDR8];
300 t_params[i].etmv4.reg_configr =
301 etm->metadata[i][CS_ETMV4_TRCCONFIGR];
302 t_params[i].etmv4.reg_traceidr =
303 etm->metadata[i][CS_ETMV4_TRCTRACEIDR];
304 }
305
306 /* Set decoder parameters to simply print the trace packets */
307 d_params.packet_printer = cs_etm__packet_dump;
308 d_params.operation = CS_ETM_OPERATION_DECODE;
309 d_params.formatted = true;
310 d_params.fsyncs = false;
311 d_params.hsyncs = false;
312 d_params.frame_aligned = true;
313 d_params.data = etmq;
314
315 etmq->decoder = cs_etm_decoder__new(etm->num_cpu, &d_params, t_params);
316
317 zfree(&t_params);
318
319 if (!etmq->decoder)
320 goto out_free;
321
322 /*
323 * Register a function to handle all memory accesses required by
324 * the trace decoder library.
325 */
326 if (cs_etm_decoder__add_mem_access_cb(etmq->decoder,
327 0x0L, ((u64) -1L),
328 cs_etm__mem_access))
329 goto out_free_decoder;
330
331 etmq->offset = 0;
332
333 return etmq;
334
335out_free_decoder:
336 cs_etm_decoder__free(etmq->decoder);
337out_free:
338 zfree(&etmq->event_buf);
339 free(etmq);
340
341 return NULL;
342}
343
344static int cs_etm__setup_queue(struct cs_etm_auxtrace *etm,
345 struct auxtrace_queue *queue,
346 unsigned int queue_nr)
347{
348 struct cs_etm_queue *etmq = queue->priv;
349
350 if (list_empty(&queue->head) || etmq)
351 return 0;
352
353 etmq = cs_etm__alloc_queue(etm, queue_nr);
354
355 if (!etmq)
356 return -ENOMEM;
357
358 queue->priv = etmq;
359
360 if (queue->cpu != -1)
361 etmq->cpu = queue->cpu;
362
363 etmq->tid = queue->tid;
364
365 return 0;
366}
367
368static int cs_etm__setup_queues(struct cs_etm_auxtrace *etm)
369{
370 unsigned int i;
371 int ret;
372
373 for (i = 0; i < etm->queues.nr_queues; i++) {
374 ret = cs_etm__setup_queue(etm, &etm->queues.queue_array[i], i);
375 if (ret)
376 return ret;
377 }
378
379 return 0;
380}
381
382static int cs_etm__update_queues(struct cs_etm_auxtrace *etm)
383{
384 if (etm->queues.new_data) {
385 etm->queues.new_data = false;
386 return cs_etm__setup_queues(etm);
387 }
388
389 return 0;
390}
391
Mathieu Poirier9f878b22018-01-17 10:52:17 -0700392static int
393cs_etm__get_trace(struct cs_etm_buffer *buff, struct cs_etm_queue *etmq)
394{
395 struct auxtrace_buffer *aux_buffer = etmq->buffer;
396 struct auxtrace_buffer *old_buffer = aux_buffer;
397 struct auxtrace_queue *queue;
398
399 queue = &etmq->etm->queues.queue_array[etmq->queue_nr];
400
401 aux_buffer = auxtrace_buffer__next(queue, aux_buffer);
402
403 /* If no more data, drop the previous auxtrace_buffer and return */
404 if (!aux_buffer) {
405 if (old_buffer)
406 auxtrace_buffer__drop_data(old_buffer);
407 buff->len = 0;
408 return 0;
409 }
410
411 etmq->buffer = aux_buffer;
412
413 /* If the aux_buffer doesn't have data associated, try to load it */
414 if (!aux_buffer->data) {
415 /* get the file desc associated with the perf data file */
416 int fd = perf_data__fd(etmq->etm->session->data);
417
418 aux_buffer->data = auxtrace_buffer__get_data(aux_buffer, fd);
419 if (!aux_buffer->data)
420 return -ENOMEM;
421 }
422
423 /* If valid, drop the previous buffer */
424 if (old_buffer)
425 auxtrace_buffer__drop_data(old_buffer);
426
427 buff->offset = aux_buffer->offset;
428 buff->len = aux_buffer->size;
429 buff->buf = aux_buffer->data;
430
431 buff->ref_timestamp = aux_buffer->reference;
432
433 return buff->len;
434}
435
436static void cs_etm__set_pid_tid_cpu(struct cs_etm_auxtrace *etm,
437 struct auxtrace_queue *queue)
438{
439 struct cs_etm_queue *etmq = queue->priv;
440
441 /* CPU-wide tracing isn't supported yet */
442 if (queue->tid == -1)
443 return;
444
445 if ((!etmq->thread) && (etmq->tid != -1))
446 etmq->thread = machine__find_thread(etm->machine, -1,
447 etmq->tid);
448
449 if (etmq->thread) {
450 etmq->pid = etmq->thread->pid_;
451 if (queue->cpu == -1)
452 etmq->cpu = etmq->thread->cpu;
453 }
454}
455
456static int cs_etm__run_decoder(struct cs_etm_queue *etmq)
457{
458 struct cs_etm_auxtrace *etm = etmq->etm;
459 struct cs_etm_buffer buffer;
460 size_t buffer_used, processed;
461 int err = 0;
462
463 if (!etm->kernel_start)
464 etm->kernel_start = machine__kernel_start(etm->machine);
465
466 /* Go through each buffer in the queue and decode them one by one */
467more:
468 buffer_used = 0;
469 memset(&buffer, 0, sizeof(buffer));
470 err = cs_etm__get_trace(&buffer, etmq);
471 if (err <= 0)
472 return err;
473 /*
474 * We cannot assume consecutive blocks in the data file are contiguous,
475 * reset the decoder to force re-sync.
476 */
477 err = cs_etm_decoder__reset(etmq->decoder);
478 if (err != 0)
479 return err;
480
481 /* Run trace decoder until buffer consumed or end of trace */
482 do {
483 processed = 0;
484
485 err = cs_etm_decoder__process_data_block(
486 etmq->decoder,
487 etmq->offset,
488 &buffer.buf[buffer_used],
489 buffer.len - buffer_used,
490 &processed);
491
492 if (err)
493 return err;
494
495 etmq->offset += processed;
496 buffer_used += processed;
497 } while (buffer.len > buffer_used);
498
499goto more;
500
501 return err;
502}
503
504static int cs_etm__process_timeless_queues(struct cs_etm_auxtrace *etm,
505 pid_t tid, u64 time_)
506{
507 unsigned int i;
508 struct auxtrace_queues *queues = &etm->queues;
509
510 for (i = 0; i < queues->nr_queues; i++) {
511 struct auxtrace_queue *queue = &etm->queues.queue_array[i];
512 struct cs_etm_queue *etmq = queue->priv;
513
514 if (etmq && ((tid == -1) || (etmq->tid == tid))) {
515 etmq->time = time_;
516 cs_etm__set_pid_tid_cpu(etm, queue);
517 cs_etm__run_decoder(etmq);
518 }
519 }
520
521 return 0;
522}
523
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700524static int cs_etm__process_event(struct perf_session *session,
525 union perf_event *event,
526 struct perf_sample *sample,
527 struct perf_tool *tool)
528{
Mathieu Poirier20d9c472018-01-17 10:52:16 -0700529 int err = 0;
530 u64 timestamp;
531 struct cs_etm_auxtrace *etm = container_of(session->auxtrace,
532 struct cs_etm_auxtrace,
533 auxtrace);
534
Mathieu Poirier20d9c472018-01-17 10:52:16 -0700535 if (dump_trace)
536 return 0;
537
538 if (!tool->ordered_events) {
539 pr_err("CoreSight ETM Trace requires ordered events\n");
540 return -EINVAL;
541 }
542
543 if (!etm->timeless_decoding)
544 return -EINVAL;
545
546 if (sample->time && (sample->time != (u64) -1))
547 timestamp = sample->time;
548 else
549 timestamp = 0;
550
551 if (timestamp || etm->timeless_decoding) {
552 err = cs_etm__update_queues(etm);
553 if (err)
554 return err;
555 }
556
Mathieu Poirier9f878b22018-01-17 10:52:17 -0700557 if (event->header.type == PERF_RECORD_EXIT)
558 return cs_etm__process_timeless_queues(etm,
559 event->fork.tid,
560 sample->time);
561
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700562 return 0;
563}
564
565static int cs_etm__process_auxtrace_event(struct perf_session *session,
566 union perf_event *event,
Mathieu Poirier68ffe392018-01-17 10:52:13 -0700567 struct perf_tool *tool __maybe_unused)
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700568{
Mathieu Poirier68ffe392018-01-17 10:52:13 -0700569 struct cs_etm_auxtrace *etm = container_of(session->auxtrace,
570 struct cs_etm_auxtrace,
571 auxtrace);
572 if (!etm->data_queued) {
573 struct auxtrace_buffer *buffer;
574 off_t data_offset;
575 int fd = perf_data__fd(session->data);
576 bool is_pipe = perf_data__is_pipe(session->data);
577 int err;
578
579 if (is_pipe)
580 data_offset = 0;
581 else {
582 data_offset = lseek(fd, 0, SEEK_CUR);
583 if (data_offset == -1)
584 return -errno;
585 }
586
587 err = auxtrace_queues__add_event(&etm->queues, session,
588 event, data_offset, &buffer);
589 if (err)
590 return err;
591
592 if (dump_trace)
593 if (auxtrace_buffer__get_data(buffer, fd)) {
594 cs_etm__dump_event(etm, buffer);
595 auxtrace_buffer__put_data(buffer);
596 }
597 }
598
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700599 return 0;
600}
601
602static bool cs_etm__is_timeless_decoding(struct cs_etm_auxtrace *etm)
603{
604 struct perf_evsel *evsel;
605 struct perf_evlist *evlist = etm->session->evlist;
606 bool timeless_decoding = true;
607
608 /*
609 * Circle through the list of event and complain if we find one
610 * with the time bit set.
611 */
612 evlist__for_each_entry(evlist, evsel) {
613 if ((evsel->attr.sample_type & PERF_SAMPLE_TIME))
614 timeless_decoding = false;
615 }
616
617 return timeless_decoding;
618}
619
Tor Jeremiassencd8bfd82018-01-17 10:52:12 -0700620static const char * const cs_etm_global_header_fmts[] = {
621 [CS_HEADER_VERSION_0] = " Header version %llx\n",
622 [CS_PMU_TYPE_CPUS] = " PMU type/num cpus %llx\n",
623 [CS_ETM_SNAPSHOT] = " Snapshot %llx\n",
624};
625
626static const char * const cs_etm_priv_fmts[] = {
627 [CS_ETM_MAGIC] = " Magic number %llx\n",
628 [CS_ETM_CPU] = " CPU %lld\n",
629 [CS_ETM_ETMCR] = " ETMCR %llx\n",
630 [CS_ETM_ETMTRACEIDR] = " ETMTRACEIDR %llx\n",
631 [CS_ETM_ETMCCER] = " ETMCCER %llx\n",
632 [CS_ETM_ETMIDR] = " ETMIDR %llx\n",
633};
634
635static const char * const cs_etmv4_priv_fmts[] = {
636 [CS_ETM_MAGIC] = " Magic number %llx\n",
637 [CS_ETM_CPU] = " CPU %lld\n",
638 [CS_ETMV4_TRCCONFIGR] = " TRCCONFIGR %llx\n",
639 [CS_ETMV4_TRCTRACEIDR] = " TRCTRACEIDR %llx\n",
640 [CS_ETMV4_TRCIDR0] = " TRCIDR0 %llx\n",
641 [CS_ETMV4_TRCIDR1] = " TRCIDR1 %llx\n",
642 [CS_ETMV4_TRCIDR2] = " TRCIDR2 %llx\n",
643 [CS_ETMV4_TRCIDR8] = " TRCIDR8 %llx\n",
644 [CS_ETMV4_TRCAUTHSTATUS] = " TRCAUTHSTATUS %llx\n",
645};
646
647static void cs_etm__print_auxtrace_info(u64 *val, int num)
648{
649 int i, j, cpu = 0;
650
651 for (i = 0; i < CS_HEADER_VERSION_0_MAX; i++)
652 fprintf(stdout, cs_etm_global_header_fmts[i], val[i]);
653
654 for (i = CS_HEADER_VERSION_0_MAX; cpu < num; cpu++) {
655 if (val[i] == __perf_cs_etmv3_magic)
656 for (j = 0; j < CS_ETM_PRIV_MAX; j++, i++)
657 fprintf(stdout, cs_etm_priv_fmts[j], val[i]);
658 else if (val[i] == __perf_cs_etmv4_magic)
659 for (j = 0; j < CS_ETMV4_PRIV_MAX; j++, i++)
660 fprintf(stdout, cs_etmv4_priv_fmts[j], val[i]);
661 else
662 /* failure.. return */
663 return;
664 }
665}
666
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700667int cs_etm__process_auxtrace_info(union perf_event *event,
668 struct perf_session *session)
669{
670 struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info;
671 struct cs_etm_auxtrace *etm = NULL;
Tor Jeremiassencd8bfd82018-01-17 10:52:12 -0700672 struct int_node *inode;
673 unsigned int pmu_type;
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700674 int event_header_size = sizeof(struct perf_event_header);
675 int info_header_size;
676 int total_size = auxtrace_info->header.size;
Tor Jeremiassencd8bfd82018-01-17 10:52:12 -0700677 int priv_size = 0;
678 int num_cpu;
679 int err = 0, idx = -1;
680 int i, j, k;
681 u64 *ptr, *hdr = NULL;
682 u64 **metadata = NULL;
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700683
684 /*
685 * sizeof(auxtrace_info_event::type) +
686 * sizeof(auxtrace_info_event::reserved) == 8
687 */
688 info_header_size = 8;
689
690 if (total_size < (event_header_size + info_header_size))
691 return -EINVAL;
692
Tor Jeremiassencd8bfd82018-01-17 10:52:12 -0700693 priv_size = total_size - event_header_size - info_header_size;
694
695 /* First the global part */
696 ptr = (u64 *) auxtrace_info->priv;
697
698 /* Look for version '0' of the header */
699 if (ptr[0] != 0)
700 return -EINVAL;
701
702 hdr = zalloc(sizeof(*hdr) * CS_HEADER_VERSION_0_MAX);
703 if (!hdr)
704 return -ENOMEM;
705
706 /* Extract header information - see cs-etm.h for format */
707 for (i = 0; i < CS_HEADER_VERSION_0_MAX; i++)
708 hdr[i] = ptr[i];
709 num_cpu = hdr[CS_PMU_TYPE_CPUS] & 0xffffffff;
710 pmu_type = (unsigned int) ((hdr[CS_PMU_TYPE_CPUS] >> 32) &
711 0xffffffff);
712
713 /*
714 * Create an RB tree for traceID-CPU# tuple. Since the conversion has
715 * to be made for each packet that gets decoded, optimizing access in
716 * anything other than a sequential array is worth doing.
717 */
718 traceid_list = intlist__new(NULL);
719 if (!traceid_list) {
720 err = -ENOMEM;
721 goto err_free_hdr;
722 }
723
724 metadata = zalloc(sizeof(*metadata) * num_cpu);
725 if (!metadata) {
726 err = -ENOMEM;
727 goto err_free_traceid_list;
728 }
729
730 /*
731 * The metadata is stored in the auxtrace_info section and encodes
732 * the configuration of the ARM embedded trace macrocell which is
733 * required by the trace decoder to properly decode the trace due
734 * to its highly compressed nature.
735 */
736 for (j = 0; j < num_cpu; j++) {
737 if (ptr[i] == __perf_cs_etmv3_magic) {
738 metadata[j] = zalloc(sizeof(*metadata[j]) *
739 CS_ETM_PRIV_MAX);
740 if (!metadata[j]) {
741 err = -ENOMEM;
742 goto err_free_metadata;
743 }
744 for (k = 0; k < CS_ETM_PRIV_MAX; k++)
745 metadata[j][k] = ptr[i + k];
746
747 /* The traceID is our handle */
748 idx = metadata[j][CS_ETM_ETMTRACEIDR];
749 i += CS_ETM_PRIV_MAX;
750 } else if (ptr[i] == __perf_cs_etmv4_magic) {
751 metadata[j] = zalloc(sizeof(*metadata[j]) *
752 CS_ETMV4_PRIV_MAX);
753 if (!metadata[j]) {
754 err = -ENOMEM;
755 goto err_free_metadata;
756 }
757 for (k = 0; k < CS_ETMV4_PRIV_MAX; k++)
758 metadata[j][k] = ptr[i + k];
759
760 /* The traceID is our handle */
761 idx = metadata[j][CS_ETMV4_TRCTRACEIDR];
762 i += CS_ETMV4_PRIV_MAX;
763 }
764
765 /* Get an RB node for this CPU */
766 inode = intlist__findnew(traceid_list, idx);
767
768 /* Something went wrong, no need to continue */
769 if (!inode) {
770 err = PTR_ERR(inode);
771 goto err_free_metadata;
772 }
773
774 /*
775 * The node for that CPU should not be taken.
776 * Back out if that's the case.
777 */
778 if (inode->priv) {
779 err = -EINVAL;
780 goto err_free_metadata;
781 }
782 /* All good, associate the traceID with the CPU# */
783 inode->priv = &metadata[j][CS_ETM_CPU];
784 }
785
786 /*
787 * Each of CS_HEADER_VERSION_0_MAX, CS_ETM_PRIV_MAX and
788 * CS_ETMV4_PRIV_MAX mark how many double words are in the
789 * global metadata, and each cpu's metadata respectively.
790 * The following tests if the correct number of double words was
791 * present in the auxtrace info section.
792 */
793 if (i * 8 != priv_size) {
794 err = -EINVAL;
795 goto err_free_metadata;
796 }
797
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700798 etm = zalloc(sizeof(*etm));
799
Tor Jeremiassencd8bfd82018-01-17 10:52:12 -0700800 if (!etm) {
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700801 err = -ENOMEM;
Tor Jeremiassencd8bfd82018-01-17 10:52:12 -0700802 goto err_free_metadata;
803 }
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700804
805 err = auxtrace_queues__init(&etm->queues);
806 if (err)
807 goto err_free_etm;
808
809 etm->session = session;
810 etm->machine = &session->machines.host;
811
Tor Jeremiassencd8bfd82018-01-17 10:52:12 -0700812 etm->num_cpu = num_cpu;
813 etm->pmu_type = pmu_type;
814 etm->snapshot_mode = (hdr[CS_ETM_SNAPSHOT] != 0);
815 etm->metadata = metadata;
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700816 etm->auxtrace_type = auxtrace_info->type;
817 etm->timeless_decoding = cs_etm__is_timeless_decoding(etm);
818
819 etm->auxtrace.process_event = cs_etm__process_event;
820 etm->auxtrace.process_auxtrace_event = cs_etm__process_auxtrace_event;
821 etm->auxtrace.flush_events = cs_etm__flush_events;
822 etm->auxtrace.free_events = cs_etm__free_events;
823 etm->auxtrace.free = cs_etm__free;
824 session->auxtrace = &etm->auxtrace;
825
Tor Jeremiassencd8bfd82018-01-17 10:52:12 -0700826 if (dump_trace) {
827 cs_etm__print_auxtrace_info(auxtrace_info->priv, num_cpu);
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700828 return 0;
Tor Jeremiassencd8bfd82018-01-17 10:52:12 -0700829 }
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700830
831 err = auxtrace_queues__process_index(&etm->queues, session);
832 if (err)
833 goto err_free_queues;
834
835 etm->data_queued = etm->queues.populated;
836
837 return 0;
838
839err_free_queues:
840 auxtrace_queues__free(&etm->queues);
841 session->auxtrace = NULL;
842err_free_etm:
843 zfree(&etm);
Tor Jeremiassencd8bfd82018-01-17 10:52:12 -0700844err_free_metadata:
845 /* No need to check @metadata[j], free(NULL) is supported */
846 for (j = 0; j < num_cpu; j++)
847 free(metadata[j]);
848 zfree(&metadata);
849err_free_traceid_list:
850 intlist__delete(traceid_list);
851err_free_hdr:
852 zfree(&hdr);
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700853
854 return -EINVAL;
855}