Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[cris-mirror.git] / tools / perf / util / cs-etm.c
blobb9f0a53dfa653fc94d492778d8c4ce622dface71
1 /*
2 * SPDX-License-Identifier: GPL-2.0
4 * Copyright(C) 2015-2018 Linaro Limited.
6 * Author: Tor Jeremiassen <tor@ti.com>
7 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
8 */
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>
16 #include <stdlib.h>
18 #include "auxtrace.h"
19 #include "color.h"
20 #include "cs-etm.h"
21 #include "cs-etm-decoder/cs-etm-decoder.h"
22 #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"
33 #define MAX_TIMESTAMP (~0ULL)
35 struct 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;
44 u8 timeless_decoding;
45 u8 snapshot_mode;
46 u8 data_queued;
47 u8 sample_branches;
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;
58 struct 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;
73 static int cs_etm__update_queues(struct cs_etm_auxtrace *etm);
74 static int cs_etm__process_timeless_queues(struct cs_etm_auxtrace *etm,
75 pid_t tid, u64 time_);
77 static void cs_etm__packet_dump(const char *pkt_string)
79 const char *color = PERF_COLOR_BLUE;
80 int len = strlen(pkt_string);
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);
87 fflush(stdout);
90 static void cs_etm__dump_event(struct cs_etm_auxtrace *etm,
91 struct auxtrace_buffer *buffer)
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;
100 fprintf(stdout, "\n");
101 color_fprintf(stdout, color,
102 ". ... CoreSight ETM Trace data: size %zu bytes\n",
103 buffer->size);
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];
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;
127 decoder = cs_etm_decoder__new(etm->num_cpu, &d_params, t_params);
129 zfree(&t_params);
131 if (!decoder)
132 return;
133 do {
134 size_t consumed;
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;
143 buffer_used += consumed;
144 } while (buffer_used < buffer->size);
146 cs_etm_decoder__free(decoder);
149 static int cs_etm__flush_events(struct perf_session *session,
150 struct perf_tool *tool)
152 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;
159 if (!tool->ordered_events)
160 return -EINVAL;
162 if (!etm->timeless_decoding)
163 return -EINVAL;
165 ret = cs_etm__update_queues(etm);
167 if (ret < 0)
168 return ret;
170 return cs_etm__process_timeless_queues(etm, -1, MAX_TIMESTAMP - 1);
173 static void cs_etm__free_queue(void *priv)
175 struct cs_etm_queue *etmq = priv;
177 free(etmq);
180 static void cs_etm__free_events(struct perf_session *session)
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;
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;
193 auxtrace_queues__free(queues);
196 static void cs_etm__free(struct perf_session *session)
198 int i;
199 struct int_node *inode, *tmp;
200 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;
206 /* 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);
212 for (i = 0; i < aux->num_cpu; i++)
213 zfree(&aux->metadata[i]);
215 zfree(&aux->metadata);
216 zfree(&aux);
219 static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u64 address,
220 size_t size, u8 *buffer)
222 u8 cpumode;
223 u64 offset;
224 int len;
225 struct thread *thread;
226 struct machine *machine;
227 struct addr_location al;
229 if (!etmq)
230 return -1;
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;
238 thread = etmq->thread;
239 if (!thread) {
240 if (cpumode != PERF_RECORD_MISC_KERNEL)
241 return -EINVAL;
242 thread = etmq->etm->unknown_thread;
245 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, address, &al);
247 if (!al.map || !al.map->dso)
248 return 0;
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;
254 offset = al.map->map_ip(al.map, address);
256 map__load(al.map);
258 len = dso__data_read_offset(al.map->dso, machine, offset, buffer, size);
260 if (len <= 0)
261 return 0;
263 return len;
266 static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm,
267 unsigned int queue_nr)
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;
274 etmq = zalloc(sizeof(*etmq));
275 if (!etmq)
276 return NULL;
278 etmq->event_buf = malloc(PERF_SAMPLE_MAX_SIZE);
279 if (!etmq->event_buf)
280 goto out_free;
282 etmq->etm = etm;
283 etmq->queue_nr = queue_nr;
284 etmq->pid = -1;
285 etmq->tid = -1;
286 etmq->cpu = -1;
288 /* Use metadata to fill in trace parameters for trace decoder */
289 t_params = zalloc(sizeof(*t_params) * etm->num_cpu);
291 if (!t_params)
292 goto out_free;
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];
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;
315 etmq->decoder = cs_etm_decoder__new(etm->num_cpu, &d_params, t_params);
317 zfree(&t_params);
319 if (!etmq->decoder)
320 goto out_free;
323 * Register a function to handle all memory accesses required by
324 * the trace decoder library.
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;
331 etmq->offset = 0;
333 return etmq;
335 out_free_decoder:
336 cs_etm_decoder__free(etmq->decoder);
337 out_free:
338 zfree(&etmq->event_buf);
339 free(etmq);
341 return NULL;
344 static int cs_etm__setup_queue(struct cs_etm_auxtrace *etm,
345 struct auxtrace_queue *queue,
346 unsigned int queue_nr)
348 struct cs_etm_queue *etmq = queue->priv;
350 if (list_empty(&queue->head) || etmq)
351 return 0;
353 etmq = cs_etm__alloc_queue(etm, queue_nr);
355 if (!etmq)
356 return -ENOMEM;
358 queue->priv = etmq;
360 if (queue->cpu != -1)
361 etmq->cpu = queue->cpu;
363 etmq->tid = queue->tid;
365 return 0;
368 static int cs_etm__setup_queues(struct cs_etm_auxtrace *etm)
370 unsigned int i;
371 int ret;
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;
379 return 0;
382 static int cs_etm__update_queues(struct cs_etm_auxtrace *etm)
384 if (etm->queues.new_data) {
385 etm->queues.new_data = false;
386 return cs_etm__setup_queues(etm);
389 return 0;
392 static int
393 cs_etm__get_trace(struct cs_etm_buffer *buff, struct cs_etm_queue *etmq)
395 struct auxtrace_buffer *aux_buffer = etmq->buffer;
396 struct auxtrace_buffer *old_buffer = aux_buffer;
397 struct auxtrace_queue *queue;
399 queue = &etmq->etm->queues.queue_array[etmq->queue_nr];
401 aux_buffer = auxtrace_buffer__next(queue, aux_buffer);
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;
411 etmq->buffer = aux_buffer;
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);
418 aux_buffer->data = auxtrace_buffer__get_data(aux_buffer, fd);
419 if (!aux_buffer->data)
420 return -ENOMEM;
423 /* If valid, drop the previous buffer */
424 if (old_buffer)
425 auxtrace_buffer__drop_data(old_buffer);
427 buff->offset = aux_buffer->offset;
428 buff->len = aux_buffer->size;
429 buff->buf = aux_buffer->data;
431 buff->ref_timestamp = aux_buffer->reference;
433 return buff->len;
436 static void cs_etm__set_pid_tid_cpu(struct cs_etm_auxtrace *etm,
437 struct auxtrace_queue *queue)
439 struct cs_etm_queue *etmq = queue->priv;
441 /* CPU-wide tracing isn't supported yet */
442 if (queue->tid == -1)
443 return;
445 if ((!etmq->thread) && (etmq->tid != -1))
446 etmq->thread = machine__find_thread(etm->machine, -1,
447 etmq->tid);
449 if (etmq->thread) {
450 etmq->pid = etmq->thread->pid_;
451 if (queue->cpu == -1)
452 etmq->cpu = etmq->thread->cpu;
457 * The cs etm packet encodes an instruction range between a branch target
458 * and the next taken branch. Generate sample accordingly.
460 static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq,
461 struct cs_etm_packet *packet)
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;
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);
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;
485 ret = perf_session__deliver_synth_event(etm->session, event, &sample);
487 if (ret)
488 pr_err(
489 "CS ETM Trace: failed to deliver instruction event, error %d\n",
490 ret);
492 return ret;
495 struct cs_etm_synth {
496 struct perf_tool dummy_tool;
497 struct perf_session *session;
500 static 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)
505 struct cs_etm_synth *cs_etm_synth =
506 container_of(tool, struct cs_etm_synth, dummy_tool);
508 return perf_session__deliver_synth_event(cs_etm_synth->session,
509 event, NULL);
512 static int cs_etm__synth_event(struct perf_session *session,
513 struct perf_event_attr *attr, u64 id)
515 struct cs_etm_synth cs_etm_synth;
517 memset(&cs_etm_synth, 0, sizeof(struct cs_etm_synth));
518 cs_etm_synth.session = session;
520 return perf_event__synthesize_attr(&cs_etm_synth.dummy_tool, attr, 1,
521 &id, cs_etm__event_synth);
524 static int cs_etm__synth_events(struct cs_etm_auxtrace *etm,
525 struct perf_session *session)
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;
534 evlist__for_each_entry(evlist, evsel) {
535 if (evsel->attr.type == etm->pmu_type) {
536 found = true;
537 break;
541 if (!found) {
542 pr_debug("No selected events with CoreSight Trace data\n");
543 return 0;
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;
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;
565 /* create new id val to be a fixed offset from evsel id */
566 id = evsel->id[0] + 1000000000;
568 if (!id)
569 id = 1;
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;
583 return 0;
586 static int cs_etm__sample(struct cs_etm_queue *etmq)
588 int ret;
589 struct cs_etm_packet packet;
591 while (1) {
592 ret = cs_etm_decoder__get_packet(etmq->decoder, &packet);
593 if (ret <= 0)
594 return ret;
597 * If the packet contains an instruction range, generate an
598 * instruction sequence event.
600 if (packet.sample_type & CS_ETM_RANGE)
601 cs_etm__synth_branch_sample(etmq, &packet);
604 return 0;
607 static int cs_etm__run_decoder(struct cs_etm_queue *etmq)
609 struct cs_etm_auxtrace *etm = etmq->etm;
610 struct cs_etm_buffer buffer;
611 size_t buffer_used, processed;
612 int err = 0;
614 if (!etm->kernel_start)
615 etm->kernel_start = machine__kernel_start(etm->machine);
617 /* Go through each buffer in the queue and decode them one by one */
618 more:
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;
625 * We cannot assume consecutive blocks in the data file are contiguous,
626 * reset the decoder to force re-sync.
628 err = cs_etm_decoder__reset(etmq->decoder);
629 if (err != 0)
630 return err;
632 /* Run trace decoder until buffer consumed or end of trace */
633 do {
634 processed = 0;
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);
643 if (err)
644 return err;
646 etmq->offset += processed;
647 buffer_used += processed;
650 * Nothing to do with an error condition, let's hope the next
651 * chunk will be better.
653 err = cs_etm__sample(etmq);
654 } while (buffer.len > buffer_used);
656 goto more;
658 return err;
661 static int cs_etm__process_timeless_queues(struct cs_etm_auxtrace *etm,
662 pid_t tid, u64 time_)
664 unsigned int i;
665 struct auxtrace_queues *queues = &etm->queues;
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;
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);
678 return 0;
681 static int cs_etm__process_event(struct perf_session *session,
682 union perf_event *event,
683 struct perf_sample *sample,
684 struct perf_tool *tool)
686 int err = 0;
687 u64 timestamp;
688 struct cs_etm_auxtrace *etm = container_of(session->auxtrace,
689 struct cs_etm_auxtrace,
690 auxtrace);
692 if (dump_trace)
693 return 0;
695 if (!tool->ordered_events) {
696 pr_err("CoreSight ETM Trace requires ordered events\n");
697 return -EINVAL;
700 if (!etm->timeless_decoding)
701 return -EINVAL;
703 if (sample->time && (sample->time != (u64) -1))
704 timestamp = sample->time;
705 else
706 timestamp = 0;
708 if (timestamp || etm->timeless_decoding) {
709 err = cs_etm__update_queues(etm);
710 if (err)
711 return err;
714 if (event->header.type == PERF_RECORD_EXIT)
715 return cs_etm__process_timeless_queues(etm,
716 event->fork.tid,
717 sample->time);
719 return 0;
722 static int cs_etm__process_auxtrace_event(struct perf_session *session,
723 union perf_event *event,
724 struct perf_tool *tool __maybe_unused)
726 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;
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;
744 err = auxtrace_queues__add_event(&etm->queues, session,
745 event, data_offset, &buffer);
746 if (err)
747 return err;
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);
756 return 0;
759 static bool cs_etm__is_timeless_decoding(struct cs_etm_auxtrace *etm)
761 struct perf_evsel *evsel;
762 struct perf_evlist *evlist = etm->session->evlist;
763 bool timeless_decoding = true;
766 * Circle through the list of event and complain if we find one
767 * with the time bit set.
769 evlist__for_each_entry(evlist, evsel) {
770 if ((evsel->attr.sample_type & PERF_SAMPLE_TIME))
771 timeless_decoding = false;
774 return timeless_decoding;
777 static 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",
783 static 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",
792 static 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",
804 static void cs_etm__print_auxtrace_info(u64 *val, int num)
806 int i, j, cpu = 0;
808 for (i = 0; i < CS_HEADER_VERSION_0_MAX; i++)
809 fprintf(stdout, cs_etm_global_header_fmts[i], val[i]);
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;
824 int cs_etm__process_auxtrace_info(union perf_event *event,
825 struct perf_session *session)
827 struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info;
828 struct cs_etm_auxtrace *etm = NULL;
829 struct int_node *inode;
830 unsigned int pmu_type;
831 int event_header_size = sizeof(struct perf_event_header);
832 int info_header_size;
833 int total_size = auxtrace_info->header.size;
834 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;
842 * sizeof(auxtrace_info_event::type) +
843 * sizeof(auxtrace_info_event::reserved) == 8
845 info_header_size = 8;
847 if (total_size < (event_header_size + info_header_size))
848 return -EINVAL;
850 priv_size = total_size - event_header_size - info_header_size;
852 /* First the global part */
853 ptr = (u64 *) auxtrace_info->priv;
855 /* Look for version '0' of the header */
856 if (ptr[0] != 0)
857 return -EINVAL;
859 hdr = zalloc(sizeof(*hdr) * CS_HEADER_VERSION_0_MAX);
860 if (!hdr)
861 return -ENOMEM;
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);
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.
875 traceid_list = intlist__new(NULL);
876 if (!traceid_list) {
877 err = -ENOMEM;
878 goto err_free_hdr;
881 metadata = zalloc(sizeof(*metadata) * num_cpu);
882 if (!metadata) {
883 err = -ENOMEM;
884 goto err_free_traceid_list;
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.
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;
901 for (k = 0; k < CS_ETM_PRIV_MAX; k++)
902 metadata[j][k] = ptr[i + k];
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;
914 for (k = 0; k < CS_ETMV4_PRIV_MAX; k++)
915 metadata[j][k] = ptr[i + k];
917 /* The traceID is our handle */
918 idx = metadata[j][CS_ETMV4_TRCTRACEIDR];
919 i += CS_ETMV4_PRIV_MAX;
922 /* Get an RB node for this CPU */
923 inode = intlist__findnew(traceid_list, idx);
925 /* Something went wrong, no need to continue */
926 if (!inode) {
927 err = PTR_ERR(inode);
928 goto err_free_metadata;
932 * The node for that CPU should not be taken.
933 * Back out if that's the case.
935 if (inode->priv) {
936 err = -EINVAL;
937 goto err_free_metadata;
939 /* All good, associate the traceID with the CPU# */
940 inode->priv = &metadata[j][CS_ETM_CPU];
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.
950 if (i * 8 != priv_size) {
951 err = -EINVAL;
952 goto err_free_metadata;
955 etm = zalloc(sizeof(*etm));
957 if (!etm) {
958 err = -ENOMEM;
959 goto err_free_metadata;
962 err = auxtrace_queues__init(&etm->queues);
963 if (err)
964 goto err_free_etm;
966 etm->session = session;
967 etm->machine = &session->machines.host;
969 etm->num_cpu = num_cpu;
970 etm->pmu_type = pmu_type;
971 etm->snapshot_mode = (hdr[CS_ETM_SNAPSHOT] != 0);
972 etm->metadata = metadata;
973 etm->auxtrace_type = auxtrace_info->type;
974 etm->timeless_decoding = cs_etm__is_timeless_decoding(etm);
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;
983 if (dump_trace) {
984 cs_etm__print_auxtrace_info(auxtrace_info->priv, num_cpu);
985 return 0;
988 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;
995 err = cs_etm__synth_events(etm, session);
996 if (err)
997 goto err_free_queues;
999 err = auxtrace_queues__process_index(&etm->queues, session);
1000 if (err)
1001 goto err_free_queues;
1003 etm->data_queued = etm->queues.populated;
1005 return 0;
1007 err_free_queues:
1008 auxtrace_queues__free(&etm->queues);
1009 session->auxtrace = NULL;
1010 err_free_etm:
1011 zfree(&etm);
1012 err_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);
1017 err_free_traceid_list:
1018 intlist__delete(traceid_list);
1019 err_free_hdr:
1020 zfree(&hdr);
1022 return -EINVAL;