blob: f47797101857d0fb234a821b22009e802704a962 [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"
21#include "debug.h"
22#include "evlist.h"
23#include "intlist.h"
24#include "machine.h"
25#include "map.h"
26#include "perf.h"
27#include "thread.h"
28#include "thread_map.h"
29#include "thread-stack.h"
30#include "util.h"
31
32#define MAX_TIMESTAMP (~0ULL)
33
34struct cs_etm_auxtrace {
35 struct auxtrace auxtrace;
36 struct auxtrace_queues queues;
37 struct auxtrace_heap heap;
38 struct itrace_synth_opts synth_opts;
39 struct perf_session *session;
40 struct machine *machine;
41 struct thread *unknown_thread;
42
43 u8 timeless_decoding;
44 u8 snapshot_mode;
45 u8 data_queued;
46 u8 sample_branches;
47
48 int num_cpu;
49 u32 auxtrace_type;
50 u64 branches_sample_type;
51 u64 branches_id;
52 u64 **metadata;
53 u64 kernel_start;
54 unsigned int pmu_type;
55};
56
57struct cs_etm_queue {
58 struct cs_etm_auxtrace *etm;
59 struct thread *thread;
60 struct cs_etm_decoder *decoder;
61 struct auxtrace_buffer *buffer;
62 const struct cs_etm_state *state;
63 union perf_event *event_buf;
64 unsigned int queue_nr;
65 pid_t pid, tid;
66 int cpu;
67 u64 time;
68 u64 timestamp;
69 u64 offset;
70};
71
72static int cs_etm__flush_events(struct perf_session *session,
73 struct perf_tool *tool)
74{
75 (void) session;
76 (void) tool;
77 return 0;
78}
79
80static void cs_etm__free_queue(void *priv)
81{
82 struct cs_etm_queue *etmq = priv;
83
84 free(etmq);
85}
86
87static void cs_etm__free_events(struct perf_session *session)
88{
89 unsigned int i;
90 struct cs_etm_auxtrace *aux = container_of(session->auxtrace,
91 struct cs_etm_auxtrace,
92 auxtrace);
93 struct auxtrace_queues *queues = &aux->queues;
94
95 for (i = 0; i < queues->nr_queues; i++) {
96 cs_etm__free_queue(queues->queue_array[i].priv);
97 queues->queue_array[i].priv = NULL;
98 }
99
100 auxtrace_queues__free(queues);
101}
102
103static void cs_etm__free(struct perf_session *session)
104{
105 struct cs_etm_auxtrace *aux = container_of(session->auxtrace,
106 struct cs_etm_auxtrace,
107 auxtrace);
108 cs_etm__free_events(session);
109 session->auxtrace = NULL;
110
111 zfree(&aux);
112}
113
114static int cs_etm__process_event(struct perf_session *session,
115 union perf_event *event,
116 struct perf_sample *sample,
117 struct perf_tool *tool)
118{
119 (void) session;
120 (void) event;
121 (void) sample;
122 (void) tool;
123 return 0;
124}
125
126static int cs_etm__process_auxtrace_event(struct perf_session *session,
127 union perf_event *event,
128 struct perf_tool *tool)
129{
130 (void) session;
131 (void) event;
132 (void) tool;
133 return 0;
134}
135
136static bool cs_etm__is_timeless_decoding(struct cs_etm_auxtrace *etm)
137{
138 struct perf_evsel *evsel;
139 struct perf_evlist *evlist = etm->session->evlist;
140 bool timeless_decoding = true;
141
142 /*
143 * Circle through the list of event and complain if we find one
144 * with the time bit set.
145 */
146 evlist__for_each_entry(evlist, evsel) {
147 if ((evsel->attr.sample_type & PERF_SAMPLE_TIME))
148 timeless_decoding = false;
149 }
150
151 return timeless_decoding;
152}
153
154int cs_etm__process_auxtrace_info(union perf_event *event,
155 struct perf_session *session)
156{
157 struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info;
158 struct cs_etm_auxtrace *etm = NULL;
159 int event_header_size = sizeof(struct perf_event_header);
160 int info_header_size;
161 int total_size = auxtrace_info->header.size;
162 int err = 0;
163
164 /*
165 * sizeof(auxtrace_info_event::type) +
166 * sizeof(auxtrace_info_event::reserved) == 8
167 */
168 info_header_size = 8;
169
170 if (total_size < (event_header_size + info_header_size))
171 return -EINVAL;
172
173 etm = zalloc(sizeof(*etm));
174
175 if (!etm)
176 err = -ENOMEM;
177
178 err = auxtrace_queues__init(&etm->queues);
179 if (err)
180 goto err_free_etm;
181
182 etm->session = session;
183 etm->machine = &session->machines.host;
184
185 etm->auxtrace_type = auxtrace_info->type;
186 etm->timeless_decoding = cs_etm__is_timeless_decoding(etm);
187
188 etm->auxtrace.process_event = cs_etm__process_event;
189 etm->auxtrace.process_auxtrace_event = cs_etm__process_auxtrace_event;
190 etm->auxtrace.flush_events = cs_etm__flush_events;
191 etm->auxtrace.free_events = cs_etm__free_events;
192 etm->auxtrace.free = cs_etm__free;
193 session->auxtrace = &etm->auxtrace;
194
195 if (dump_trace)
196 return 0;
197
198 err = auxtrace_queues__process_index(&etm->queues, session);
199 if (err)
200 goto err_free_queues;
201
202 etm->data_queued = etm->queues.populated;
203
204 return 0;
205
206err_free_queues:
207 auxtrace_queues__free(&etm->queues);
208 session->auxtrace = NULL;
209err_free_etm:
210 zfree(&etm);
211
212 return -EINVAL;
213}