]> asedeno.scripts.mit.edu Git - linux.git/blob - tools/perf/util/cs-etm.c
f47797101857d0fb234a821b22009e802704a962
[linux.git] / tools / perf / util / cs-etm.c
1 /*
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
34 struct 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
57 struct 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
72 static 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
80 static void cs_etm__free_queue(void *priv)
81 {
82         struct cs_etm_queue *etmq = priv;
83
84         free(etmq);
85 }
86
87 static 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
103 static 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
114 static 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
126 static 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
136 static 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
154 int 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
206 err_free_queues:
207         auxtrace_queues__free(&etm->queues);
208         session->auxtrace = NULL;
209 err_free_etm:
210         zfree(&etm);
211
212         return -EINVAL;
213 }