blob: b9f0a53dfa653fc94d492778d8c4ce622dface71 [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
Mathieu Poirierb12235b2018-01-17 10:52:18 -0700456/*
457 * The cs etm packet encodes an instruction range between a branch target
458 * and the next taken branch. Generate sample accordingly.
459 */
460static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq,
461 struct cs_etm_packet *packet)
462{
463 int ret = 0;
464 struct cs_etm_auxtrace *etm = etmq->etm;
465 struct perf_sample sample = {.ip = 0,};
466 union perf_event *event = etmq->event_buf;
467 u64 start_addr = packet->start_addr;
468 u64 end_addr = packet->end_addr;
469
470 event->sample.header.type = PERF_RECORD_SAMPLE;
471 event->sample.header.misc = PERF_RECORD_MISC_USER;
472 event->sample.header.size = sizeof(struct perf_event_header);
473
474 sample.ip = start_addr;
475 sample.pid = etmq->pid;
476 sample.tid = etmq->tid;
477 sample.addr = end_addr;
478 sample.id = etmq->etm->branches_id;
479 sample.stream_id = etmq->etm->branches_id;
480 sample.period = 1;
481 sample.cpu = packet->cpu;
482 sample.flags = 0;
483 sample.cpumode = PERF_RECORD_MISC_USER;
484
485 ret = perf_session__deliver_synth_event(etm->session, event, &sample);
486
487 if (ret)
488 pr_err(
489 "CS ETM Trace: failed to deliver instruction event, error %d\n",
490 ret);
491
492 return ret;
493}
494
495struct cs_etm_synth {
496 struct perf_tool dummy_tool;
497 struct perf_session *session;
498};
499
500static int cs_etm__event_synth(struct perf_tool *tool,
501 union perf_event *event,
502 struct perf_sample *sample __maybe_unused,
503 struct machine *machine __maybe_unused)
504{
505 struct cs_etm_synth *cs_etm_synth =
506 container_of(tool, struct cs_etm_synth, dummy_tool);
507
508 return perf_session__deliver_synth_event(cs_etm_synth->session,
509 event, NULL);
510}
511
512static int cs_etm__synth_event(struct perf_session *session,
513 struct perf_event_attr *attr, u64 id)
514{
515 struct cs_etm_synth cs_etm_synth;
516
517 memset(&cs_etm_synth, 0, sizeof(struct cs_etm_synth));
518 cs_etm_synth.session = session;
519
520 return perf_event__synthesize_attr(&cs_etm_synth.dummy_tool, attr, 1,
521 &id, cs_etm__event_synth);
522}
523
524static int cs_etm__synth_events(struct cs_etm_auxtrace *etm,
525 struct perf_session *session)
526{
527 struct perf_evlist *evlist = session->evlist;
528 struct perf_evsel *evsel;
529 struct perf_event_attr attr;
530 bool found = false;
531 u64 id;
532 int err;
533
534 evlist__for_each_entry(evlist, evsel) {
535 if (evsel->attr.type == etm->pmu_type) {
536 found = true;
537 break;
538 }
539 }
540
541 if (!found) {
542 pr_debug("No selected events with CoreSight Trace data\n");
543 return 0;
544 }
545
546 memset(&attr, 0, sizeof(struct perf_event_attr));
547 attr.size = sizeof(struct perf_event_attr);
548 attr.type = PERF_TYPE_HARDWARE;
549 attr.sample_type = evsel->attr.sample_type & PERF_SAMPLE_MASK;
550 attr.sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID |
551 PERF_SAMPLE_PERIOD;
552 if (etm->timeless_decoding)
553 attr.sample_type &= ~(u64)PERF_SAMPLE_TIME;
554 else
555 attr.sample_type |= PERF_SAMPLE_TIME;
556
557 attr.exclude_user = evsel->attr.exclude_user;
558 attr.exclude_kernel = evsel->attr.exclude_kernel;
559 attr.exclude_hv = evsel->attr.exclude_hv;
560 attr.exclude_host = evsel->attr.exclude_host;
561 attr.exclude_guest = evsel->attr.exclude_guest;
562 attr.sample_id_all = evsel->attr.sample_id_all;
563 attr.read_format = evsel->attr.read_format;
564
565 /* create new id val to be a fixed offset from evsel id */
566 id = evsel->id[0] + 1000000000;
567
568 if (!id)
569 id = 1;
570
571 if (etm->synth_opts.branches) {
572 attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
573 attr.sample_period = 1;
574 attr.sample_type |= PERF_SAMPLE_ADDR;
575 err = cs_etm__synth_event(session, &attr, id);
576 if (err)
577 return err;
578 etm->sample_branches = true;
579 etm->branches_sample_type = attr.sample_type;
580 etm->branches_id = id;
581 }
582
583 return 0;
584}
585
586static int cs_etm__sample(struct cs_etm_queue *etmq)
587{
588 int ret;
589 struct cs_etm_packet packet;
590
591 while (1) {
592 ret = cs_etm_decoder__get_packet(etmq->decoder, &packet);
593 if (ret <= 0)
594 return ret;
595
596 /*
597 * If the packet contains an instruction range, generate an
598 * instruction sequence event.
599 */
600 if (packet.sample_type & CS_ETM_RANGE)
601 cs_etm__synth_branch_sample(etmq, &packet);
602 }
603
604 return 0;
605}
606
Mathieu Poirier9f878b22018-01-17 10:52:17 -0700607static int cs_etm__run_decoder(struct cs_etm_queue *etmq)
608{
609 struct cs_etm_auxtrace *etm = etmq->etm;
610 struct cs_etm_buffer buffer;
611 size_t buffer_used, processed;
612 int err = 0;
613
614 if (!etm->kernel_start)
615 etm->kernel_start = machine__kernel_start(etm->machine);
616
617 /* Go through each buffer in the queue and decode them one by one */
618more:
619 buffer_used = 0;
620 memset(&buffer, 0, sizeof(buffer));
621 err = cs_etm__get_trace(&buffer, etmq);
622 if (err <= 0)
623 return err;
624 /*
625 * We cannot assume consecutive blocks in the data file are contiguous,
626 * reset the decoder to force re-sync.
627 */
628 err = cs_etm_decoder__reset(etmq->decoder);
629 if (err != 0)
630 return err;
631
632 /* Run trace decoder until buffer consumed or end of trace */
633 do {
634 processed = 0;
635
636 err = cs_etm_decoder__process_data_block(
637 etmq->decoder,
638 etmq->offset,
639 &buffer.buf[buffer_used],
640 buffer.len - buffer_used,
641 &processed);
642
643 if (err)
644 return err;
645
646 etmq->offset += processed;
647 buffer_used += processed;
Mathieu Poirierb12235b2018-01-17 10:52:18 -0700648
649 /*
650 * Nothing to do with an error condition, let's hope the next
651 * chunk will be better.
652 */
653 err = cs_etm__sample(etmq);
Mathieu Poirier9f878b22018-01-17 10:52:17 -0700654 } while (buffer.len > buffer_used);
655
656goto more;
657
658 return err;
659}
660
661static int cs_etm__process_timeless_queues(struct cs_etm_auxtrace *etm,
662 pid_t tid, u64 time_)
663{
664 unsigned int i;
665 struct auxtrace_queues *queues = &etm->queues;
666
667 for (i = 0; i < queues->nr_queues; i++) {
668 struct auxtrace_queue *queue = &etm->queues.queue_array[i];
669 struct cs_etm_queue *etmq = queue->priv;
670
671 if (etmq && ((tid == -1) || (etmq->tid == tid))) {
672 etmq->time = time_;
673 cs_etm__set_pid_tid_cpu(etm, queue);
674 cs_etm__run_decoder(etmq);
675 }
676 }
677
678 return 0;
679}
680
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700681static int cs_etm__process_event(struct perf_session *session,
682 union perf_event *event,
683 struct perf_sample *sample,
684 struct perf_tool *tool)
685{
Mathieu Poirier20d9c472018-01-17 10:52:16 -0700686 int err = 0;
687 u64 timestamp;
688 struct cs_etm_auxtrace *etm = container_of(session->auxtrace,
689 struct cs_etm_auxtrace,
690 auxtrace);
691
Mathieu Poirier20d9c472018-01-17 10:52:16 -0700692 if (dump_trace)
693 return 0;
694
695 if (!tool->ordered_events) {
696 pr_err("CoreSight ETM Trace requires ordered events\n");
697 return -EINVAL;
698 }
699
700 if (!etm->timeless_decoding)
701 return -EINVAL;
702
703 if (sample->time && (sample->time != (u64) -1))
704 timestamp = sample->time;
705 else
706 timestamp = 0;
707
708 if (timestamp || etm->timeless_decoding) {
709 err = cs_etm__update_queues(etm);
710 if (err)
711 return err;
712 }
713
Mathieu Poirier9f878b22018-01-17 10:52:17 -0700714 if (event->header.type == PERF_RECORD_EXIT)
715 return cs_etm__process_timeless_queues(etm,
716 event->fork.tid,
717 sample->time);
718
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700719 return 0;
720}
721
722static int cs_etm__process_auxtrace_event(struct perf_session *session,
723 union perf_event *event,
Mathieu Poirier68ffe392018-01-17 10:52:13 -0700724 struct perf_tool *tool __maybe_unused)
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700725{
Mathieu Poirier68ffe392018-01-17 10:52:13 -0700726 struct cs_etm_auxtrace *etm = container_of(session->auxtrace,
727 struct cs_etm_auxtrace,
728 auxtrace);
729 if (!etm->data_queued) {
730 struct auxtrace_buffer *buffer;
731 off_t data_offset;
732 int fd = perf_data__fd(session->data);
733 bool is_pipe = perf_data__is_pipe(session->data);
734 int err;
735
736 if (is_pipe)
737 data_offset = 0;
738 else {
739 data_offset = lseek(fd, 0, SEEK_CUR);
740 if (data_offset == -1)
741 return -errno;
742 }
743
744 err = auxtrace_queues__add_event(&etm->queues, session,
745 event, data_offset, &buffer);
746 if (err)
747 return err;
748
749 if (dump_trace)
750 if (auxtrace_buffer__get_data(buffer, fd)) {
751 cs_etm__dump_event(etm, buffer);
752 auxtrace_buffer__put_data(buffer);
753 }
754 }
755
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700756 return 0;
757}
758
759static bool cs_etm__is_timeless_decoding(struct cs_etm_auxtrace *etm)
760{
761 struct perf_evsel *evsel;
762 struct perf_evlist *evlist = etm->session->evlist;
763 bool timeless_decoding = true;
764
765 /*
766 * Circle through the list of event and complain if we find one
767 * with the time bit set.
768 */
769 evlist__for_each_entry(evlist, evsel) {
770 if ((evsel->attr.sample_type & PERF_SAMPLE_TIME))
771 timeless_decoding = false;
772 }
773
774 return timeless_decoding;
775}
776
Tor Jeremiassencd8bfd82018-01-17 10:52:12 -0700777static const char * const cs_etm_global_header_fmts[] = {
778 [CS_HEADER_VERSION_0] = " Header version %llx\n",
779 [CS_PMU_TYPE_CPUS] = " PMU type/num cpus %llx\n",
780 [CS_ETM_SNAPSHOT] = " Snapshot %llx\n",
781};
782
783static const char * const cs_etm_priv_fmts[] = {
784 [CS_ETM_MAGIC] = " Magic number %llx\n",
785 [CS_ETM_CPU] = " CPU %lld\n",
786 [CS_ETM_ETMCR] = " ETMCR %llx\n",
787 [CS_ETM_ETMTRACEIDR] = " ETMTRACEIDR %llx\n",
788 [CS_ETM_ETMCCER] = " ETMCCER %llx\n",
789 [CS_ETM_ETMIDR] = " ETMIDR %llx\n",
790};
791
792static const char * const cs_etmv4_priv_fmts[] = {
793 [CS_ETM_MAGIC] = " Magic number %llx\n",
794 [CS_ETM_CPU] = " CPU %lld\n",
795 [CS_ETMV4_TRCCONFIGR] = " TRCCONFIGR %llx\n",
796 [CS_ETMV4_TRCTRACEIDR] = " TRCTRACEIDR %llx\n",
797 [CS_ETMV4_TRCIDR0] = " TRCIDR0 %llx\n",
798 [CS_ETMV4_TRCIDR1] = " TRCIDR1 %llx\n",
799 [CS_ETMV4_TRCIDR2] = " TRCIDR2 %llx\n",
800 [CS_ETMV4_TRCIDR8] = " TRCIDR8 %llx\n",
801 [CS_ETMV4_TRCAUTHSTATUS] = " TRCAUTHSTATUS %llx\n",
802};
803
804static void cs_etm__print_auxtrace_info(u64 *val, int num)
805{
806 int i, j, cpu = 0;
807
808 for (i = 0; i < CS_HEADER_VERSION_0_MAX; i++)
809 fprintf(stdout, cs_etm_global_header_fmts[i], val[i]);
810
811 for (i = CS_HEADER_VERSION_0_MAX; cpu < num; cpu++) {
812 if (val[i] == __perf_cs_etmv3_magic)
813 for (j = 0; j < CS_ETM_PRIV_MAX; j++, i++)
814 fprintf(stdout, cs_etm_priv_fmts[j], val[i]);
815 else if (val[i] == __perf_cs_etmv4_magic)
816 for (j = 0; j < CS_ETMV4_PRIV_MAX; j++, i++)
817 fprintf(stdout, cs_etmv4_priv_fmts[j], val[i]);
818 else
819 /* failure.. return */
820 return;
821 }
822}
823
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700824int cs_etm__process_auxtrace_info(union perf_event *event,
825 struct perf_session *session)
826{
827 struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info;
828 struct cs_etm_auxtrace *etm = NULL;
Tor Jeremiassencd8bfd82018-01-17 10:52:12 -0700829 struct int_node *inode;
830 unsigned int pmu_type;
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700831 int event_header_size = sizeof(struct perf_event_header);
832 int info_header_size;
833 int total_size = auxtrace_info->header.size;
Tor Jeremiassencd8bfd82018-01-17 10:52:12 -0700834 int priv_size = 0;
835 int num_cpu;
836 int err = 0, idx = -1;
837 int i, j, k;
838 u64 *ptr, *hdr = NULL;
839 u64 **metadata = NULL;
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700840
841 /*
842 * sizeof(auxtrace_info_event::type) +
843 * sizeof(auxtrace_info_event::reserved) == 8
844 */
845 info_header_size = 8;
846
847 if (total_size < (event_header_size + info_header_size))
848 return -EINVAL;
849
Tor Jeremiassencd8bfd82018-01-17 10:52:12 -0700850 priv_size = total_size - event_header_size - info_header_size;
851
852 /* First the global part */
853 ptr = (u64 *) auxtrace_info->priv;
854
855 /* Look for version '0' of the header */
856 if (ptr[0] != 0)
857 return -EINVAL;
858
859 hdr = zalloc(sizeof(*hdr) * CS_HEADER_VERSION_0_MAX);
860 if (!hdr)
861 return -ENOMEM;
862
863 /* Extract header information - see cs-etm.h for format */
864 for (i = 0; i < CS_HEADER_VERSION_0_MAX; i++)
865 hdr[i] = ptr[i];
866 num_cpu = hdr[CS_PMU_TYPE_CPUS] & 0xffffffff;
867 pmu_type = (unsigned int) ((hdr[CS_PMU_TYPE_CPUS] >> 32) &
868 0xffffffff);
869
870 /*
871 * Create an RB tree for traceID-CPU# tuple. Since the conversion has
872 * to be made for each packet that gets decoded, optimizing access in
873 * anything other than a sequential array is worth doing.
874 */
875 traceid_list = intlist__new(NULL);
876 if (!traceid_list) {
877 err = -ENOMEM;
878 goto err_free_hdr;
879 }
880
881 metadata = zalloc(sizeof(*metadata) * num_cpu);
882 if (!metadata) {
883 err = -ENOMEM;
884 goto err_free_traceid_list;
885 }
886
887 /*
888 * The metadata is stored in the auxtrace_info section and encodes
889 * the configuration of the ARM embedded trace macrocell which is
890 * required by the trace decoder to properly decode the trace due
891 * to its highly compressed nature.
892 */
893 for (j = 0; j < num_cpu; j++) {
894 if (ptr[i] == __perf_cs_etmv3_magic) {
895 metadata[j] = zalloc(sizeof(*metadata[j]) *
896 CS_ETM_PRIV_MAX);
897 if (!metadata[j]) {
898 err = -ENOMEM;
899 goto err_free_metadata;
900 }
901 for (k = 0; k < CS_ETM_PRIV_MAX; k++)
902 metadata[j][k] = ptr[i + k];
903
904 /* The traceID is our handle */
905 idx = metadata[j][CS_ETM_ETMTRACEIDR];
906 i += CS_ETM_PRIV_MAX;
907 } else if (ptr[i] == __perf_cs_etmv4_magic) {
908 metadata[j] = zalloc(sizeof(*metadata[j]) *
909 CS_ETMV4_PRIV_MAX);
910 if (!metadata[j]) {
911 err = -ENOMEM;
912 goto err_free_metadata;
913 }
914 for (k = 0; k < CS_ETMV4_PRIV_MAX; k++)
915 metadata[j][k] = ptr[i + k];
916
917 /* The traceID is our handle */
918 idx = metadata[j][CS_ETMV4_TRCTRACEIDR];
919 i += CS_ETMV4_PRIV_MAX;
920 }
921
922 /* Get an RB node for this CPU */
923 inode = intlist__findnew(traceid_list, idx);
924
925 /* Something went wrong, no need to continue */
926 if (!inode) {
927 err = PTR_ERR(inode);
928 goto err_free_metadata;
929 }
930
931 /*
932 * The node for that CPU should not be taken.
933 * Back out if that's the case.
934 */
935 if (inode->priv) {
936 err = -EINVAL;
937 goto err_free_metadata;
938 }
939 /* All good, associate the traceID with the CPU# */
940 inode->priv = &metadata[j][CS_ETM_CPU];
941 }
942
943 /*
944 * Each of CS_HEADER_VERSION_0_MAX, CS_ETM_PRIV_MAX and
945 * CS_ETMV4_PRIV_MAX mark how many double words are in the
946 * global metadata, and each cpu's metadata respectively.
947 * The following tests if the correct number of double words was
948 * present in the auxtrace info section.
949 */
950 if (i * 8 != priv_size) {
951 err = -EINVAL;
952 goto err_free_metadata;
953 }
954
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700955 etm = zalloc(sizeof(*etm));
956
Tor Jeremiassencd8bfd82018-01-17 10:52:12 -0700957 if (!etm) {
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700958 err = -ENOMEM;
Tor Jeremiassencd8bfd82018-01-17 10:52:12 -0700959 goto err_free_metadata;
960 }
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700961
962 err = auxtrace_queues__init(&etm->queues);
963 if (err)
964 goto err_free_etm;
965
966 etm->session = session;
967 etm->machine = &session->machines.host;
968
Tor Jeremiassencd8bfd82018-01-17 10:52:12 -0700969 etm->num_cpu = num_cpu;
970 etm->pmu_type = pmu_type;
971 etm->snapshot_mode = (hdr[CS_ETM_SNAPSHOT] != 0);
972 etm->metadata = metadata;
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700973 etm->auxtrace_type = auxtrace_info->type;
974 etm->timeless_decoding = cs_etm__is_timeless_decoding(etm);
975
976 etm->auxtrace.process_event = cs_etm__process_event;
977 etm->auxtrace.process_auxtrace_event = cs_etm__process_auxtrace_event;
978 etm->auxtrace.flush_events = cs_etm__flush_events;
979 etm->auxtrace.free_events = cs_etm__free_events;
980 etm->auxtrace.free = cs_etm__free;
981 session->auxtrace = &etm->auxtrace;
982
Tor Jeremiassencd8bfd82018-01-17 10:52:12 -0700983 if (dump_trace) {
984 cs_etm__print_auxtrace_info(auxtrace_info->priv, num_cpu);
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700985 return 0;
Tor Jeremiassencd8bfd82018-01-17 10:52:12 -0700986 }
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700987
Mathieu Poirierb12235b2018-01-17 10:52:18 -0700988 if (session->itrace_synth_opts && session->itrace_synth_opts->set) {
989 etm->synth_opts = *session->itrace_synth_opts;
990 } else {
991 itrace_synth_opts__set_default(&etm->synth_opts);
992 etm->synth_opts.callchain = false;
993 }
994
995 err = cs_etm__synth_events(etm, session);
996 if (err)
997 goto err_free_queues;
998
Mathieu Poirier440a23b2018-01-17 10:52:11 -0700999 err = auxtrace_queues__process_index(&etm->queues, session);
1000 if (err)
1001 goto err_free_queues;
1002
1003 etm->data_queued = etm->queues.populated;
1004
1005 return 0;
1006
1007err_free_queues:
1008 auxtrace_queues__free(&etm->queues);
1009 session->auxtrace = NULL;
1010err_free_etm:
1011 zfree(&etm);
Tor Jeremiassencd8bfd82018-01-17 10:52:12 -07001012err_free_metadata:
1013 /* No need to check @metadata[j], free(NULL) is supported */
1014 for (j = 0; j < num_cpu; j++)
1015 free(metadata[j]);
1016 zfree(&metadata);
1017err_free_traceid_list:
1018 intlist__delete(traceid_list);
1019err_free_hdr:
1020 zfree(&hdr);
Mathieu Poirier440a23b2018-01-17 10:52:11 -07001021
1022 return -EINVAL;
1023}