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>
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>
21 #include "cs-etm-decoder/cs-etm-decoder.h"
29 #include "thread_map.h"
30 #include "thread-stack.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
;
51 u64 branches_sample_type
;
55 unsigned int pmu_type
;
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
;
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
);
85 color_fprintf(stdout
, color
, " %s\n", pkt_string
);
90 static void cs_etm__dump_event(struct cs_etm_auxtrace
*etm
,
91 struct auxtrace_buffer
*buffer
)
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",
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
);
136 ret
= cs_etm_decoder__process_data_block(
137 decoder
, buffer
->offset
,
138 &((u8
*)buffer
->data
)[buffer_used
],
139 buffer
->size
- buffer_used
, &consumed
);
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
)
153 struct cs_etm_auxtrace
*etm
= container_of(session
->auxtrace
,
154 struct cs_etm_auxtrace
,
159 if (!tool
->ordered_events
)
162 if (!etm
->timeless_decoding
)
165 ret
= cs_etm__update_queues(etm
);
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
;
180 static void cs_etm__free_events(struct perf_session
*session
)
183 struct cs_etm_auxtrace
*aux
= container_of(session
->auxtrace
,
184 struct cs_etm_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
)
199 struct int_node
*inode
, *tmp
;
200 struct cs_etm_auxtrace
*aux
= container_of(session
->auxtrace
,
201 struct cs_etm_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
);
219 static u32
cs_etm__mem_access(struct cs_etm_queue
*etmq
, u64 address
,
220 size_t size
, u8
*buffer
)
225 struct thread
*thread
;
226 struct machine
*machine
;
227 struct addr_location al
;
232 machine
= etmq
->etm
->machine
;
233 if (address
>= etmq
->etm
->kernel_start
)
234 cpumode
= PERF_RECORD_MISC_KERNEL
;
236 cpumode
= PERF_RECORD_MISC_USER
;
238 thread
= etmq
->thread
;
240 if (cpumode
!= PERF_RECORD_MISC_KERNEL
)
242 thread
= etmq
->etm
->unknown_thread
;
245 thread__find_addr_map(thread
, cpumode
, MAP__FUNCTION
, address
, &al
);
247 if (!al
.map
|| !al
.map
->dso
)
250 if (al
.map
->dso
->data
.status
== DSO_DATA_STATUS_ERROR
&&
251 dso__data_status_seen(al
.map
->dso
, DSO_DATA_STATUS_SEEN_ITRACE
))
254 offset
= al
.map
->map_ip(al
.map
, address
);
258 len
= dso__data_read_offset(al
.map
->dso
, machine
, offset
, buffer
, size
);
266 static struct cs_etm_queue
*cs_etm__alloc_queue(struct cs_etm_auxtrace
*etm
,
267 unsigned int queue_nr
)
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
));
278 etmq
->event_buf
= malloc(PERF_SAMPLE_MAX_SIZE
);
279 if (!etmq
->event_buf
)
283 etmq
->queue_nr
= queue_nr
;
288 /* Use metadata to fill in trace parameters for trace decoder */
289 t_params
= zalloc(sizeof(*t_params
) * etm
->num_cpu
);
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
);
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
,
329 goto out_free_decoder
;
336 cs_etm_decoder__free(etmq
->decoder
);
338 zfree(&etmq
->event_buf
);
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
)
353 etmq
= cs_etm__alloc_queue(etm
, queue_nr
);
360 if (queue
->cpu
!= -1)
361 etmq
->cpu
= queue
->cpu
;
363 etmq
->tid
= queue
->tid
;
368 static int cs_etm__setup_queues(struct cs_etm_auxtrace
*etm
)
373 for (i
= 0; i
< etm
->queues
.nr_queues
; i
++) {
374 ret
= cs_etm__setup_queue(etm
, &etm
->queues
.queue_array
[i
], i
);
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
);
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 */
406 auxtrace_buffer__drop_data(old_buffer
);
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
)
423 /* If valid, drop the previous 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
;
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)
445 if ((!etmq
->thread
) && (etmq
->tid
!= -1))
446 etmq
->thread
= machine__find_thread(etm
->machine
, -1,
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
)
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
;
481 sample
.cpu
= packet
->cpu
;
483 sample
.cpumode
= PERF_RECORD_MISC_USER
;
485 ret
= perf_session__deliver_synth_event(etm
->session
, event
, &sample
);
489 "CS ETM Trace: failed to deliver instruction event, error %d\n",
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
,
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
;
534 evlist__for_each_entry(evlist
, evsel
) {
535 if (evsel
->attr
.type
== etm
->pmu_type
) {
542 pr_debug("No selected events with CoreSight Trace data\n");
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
|
552 if (etm
->timeless_decoding
)
553 attr
.sample_type
&= ~(u64
)PERF_SAMPLE_TIME
;
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;
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
);
578 etm
->sample_branches
= true;
579 etm
->branches_sample_type
= attr
.sample_type
;
580 etm
->branches_id
= id
;
586 static int cs_etm__sample(struct cs_etm_queue
*etmq
)
589 struct cs_etm_packet packet
;
592 ret
= cs_etm_decoder__get_packet(etmq
->decoder
, &packet
);
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
);
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
;
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 */
620 memset(&buffer
, 0, sizeof(buffer
));
621 err
= cs_etm__get_trace(&buffer
, etmq
);
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
);
632 /* Run trace decoder until buffer consumed or end of trace */
636 err
= cs_etm_decoder__process_data_block(
639 &buffer
.buf
[buffer_used
],
640 buffer
.len
- buffer_used
,
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
);
661 static int cs_etm__process_timeless_queues(struct cs_etm_auxtrace
*etm
,
662 pid_t tid
, u64 time_
)
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
))) {
673 cs_etm__set_pid_tid_cpu(etm
, queue
);
674 cs_etm__run_decoder(etmq
);
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
)
688 struct cs_etm_auxtrace
*etm
= container_of(session
->auxtrace
,
689 struct cs_etm_auxtrace
,
695 if (!tool
->ordered_events
) {
696 pr_err("CoreSight ETM Trace requires ordered events\n");
700 if (!etm
->timeless_decoding
)
703 if (sample
->time
&& (sample
->time
!= (u64
) -1))
704 timestamp
= sample
->time
;
708 if (timestamp
|| etm
->timeless_decoding
) {
709 err
= cs_etm__update_queues(etm
);
714 if (event
->header
.type
== PERF_RECORD_EXIT
)
715 return cs_etm__process_timeless_queues(etm
,
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
,
729 if (!etm
->data_queued
) {
730 struct auxtrace_buffer
*buffer
;
732 int fd
= perf_data__fd(session
->data
);
733 bool is_pipe
= perf_data__is_pipe(session
->data
);
739 data_offset
= lseek(fd
, 0, SEEK_CUR
);
740 if (data_offset
== -1)
744 err
= auxtrace_queues__add_event(&etm
->queues
, session
,
745 event
, data_offset
, &buffer
);
750 if (auxtrace_buffer__get_data(buffer
, fd
)) {
751 cs_etm__dump_event(etm
, buffer
);
752 auxtrace_buffer__put_data(buffer
);
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
)
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
]);
819 /* failure.. 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
;
836 int err
= 0, idx
= -1;
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
))
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 */
859 hdr
= zalloc(sizeof(*hdr
) * CS_HEADER_VERSION_0_MAX
);
863 /* Extract header information - see cs-etm.h for format */
864 for (i
= 0; i
< CS_HEADER_VERSION_0_MAX
; i
++)
866 num_cpu
= hdr
[CS_PMU_TYPE_CPUS
] & 0xffffffff;
867 pmu_type
= (unsigned int) ((hdr
[CS_PMU_TYPE_CPUS
] >> 32) &
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
);
881 metadata
= zalloc(sizeof(*metadata
) * num_cpu
);
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
]) *
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
]) *
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 */
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.
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
) {
952 goto err_free_metadata
;
955 etm
= zalloc(sizeof(*etm
));
959 goto err_free_metadata
;
962 err
= auxtrace_queues__init(&etm
->queues
);
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
;
984 cs_etm__print_auxtrace_info(auxtrace_info
->priv
, num_cpu
);
988 if (session
->itrace_synth_opts
&& session
->itrace_synth_opts
->set
) {
989 etm
->synth_opts
= *session
->itrace_synth_opts
;
991 itrace_synth_opts__set_default(&etm
->synth_opts
);
992 etm
->synth_opts
.callchain
= false;
995 err
= cs_etm__synth_events(etm
, session
);
997 goto err_free_queues
;
999 err
= auxtrace_queues__process_index(&etm
->queues
, session
);
1001 goto err_free_queues
;
1003 etm
->data_queued
= etm
->queues
.populated
;
1008 auxtrace_queues__free(&etm
->queues
);
1009 session
->auxtrace
= NULL
;
1013 /* No need to check @metadata[j], free(NULL) is supported */
1014 for (j
= 0; j
< num_cpu
; j
++)
1017 err_free_traceid_list
:
1018 intlist__delete(traceid_list
);