perf tools: Add support for decoding CoreSight trace data
[linux-2.6-block.git] / tools / perf / util / cs-etm-decoder / cs-etm-decoder.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/err.h>
11 #include <linux/list.h>
12 #include <stdlib.h>
13 #include <opencsd/c_api/opencsd_c_api.h>
14 #include <opencsd/etmv4/trc_pkt_types_etmv4.h>
15 #include <opencsd/ocsd_if_types.h>
16
17 #include "cs-etm.h"
18 #include "cs-etm-decoder.h"
19 #include "intlist.h"
20 #include "util.h"
21
22 #define MAX_BUFFER 1024
23
24 /* use raw logging */
25 #ifdef CS_DEBUG_RAW
26 #define CS_LOG_RAW_FRAMES
27 #ifdef CS_RAW_PACKED
28 #define CS_RAW_DEBUG_FLAGS (OCSD_DFRMTR_UNPACKED_RAW_OUT | \
29                             OCSD_DFRMTR_PACKED_RAW_OUT)
30 #else
31 #define CS_RAW_DEBUG_FLAGS (OCSD_DFRMTR_UNPACKED_RAW_OUT)
32 #endif
33 #endif
34
35 struct cs_etm_decoder {
36         void *data;
37         void (*packet_printer)(const char *msg);
38         bool trace_on;
39         dcd_tree_handle_t dcd_tree;
40         cs_etm_mem_cb_type mem_access;
41         ocsd_datapath_resp_t prev_return;
42         u32 packet_count;
43         u32 head;
44         u32 tail;
45         struct cs_etm_packet packet_buffer[MAX_BUFFER];
46 };
47
48 static void cs_etm_decoder__gen_etmv4_config(struct cs_etm_trace_params *params,
49                                              ocsd_etmv4_cfg *config)
50 {
51         config->reg_configr = params->etmv4.reg_configr;
52         config->reg_traceidr = params->etmv4.reg_traceidr;
53         config->reg_idr0 = params->etmv4.reg_idr0;
54         config->reg_idr1 = params->etmv4.reg_idr1;
55         config->reg_idr2 = params->etmv4.reg_idr2;
56         config->reg_idr8 = params->etmv4.reg_idr8;
57         config->reg_idr9 = 0;
58         config->reg_idr10 = 0;
59         config->reg_idr11 = 0;
60         config->reg_idr12 = 0;
61         config->reg_idr13 = 0;
62         config->arch_ver = ARCH_V8;
63         config->core_prof = profile_CortexA;
64 }
65
66 static void cs_etm_decoder__print_str_cb(const void *p_context,
67                                          const char *msg,
68                                          const int str_len)
69 {
70         if (p_context && str_len)
71                 ((struct cs_etm_decoder *)p_context)->packet_printer(msg);
72 }
73
74 static int
75 cs_etm_decoder__init_def_logger_printing(struct cs_etm_decoder_params *d_params,
76                                          struct cs_etm_decoder *decoder)
77 {
78         int ret = 0;
79
80         if (d_params->packet_printer == NULL)
81                 return -1;
82
83         decoder->packet_printer = d_params->packet_printer;
84
85         /*
86          * Set up a library default logger to process any printers
87          * (packet/raw frame) we add later.
88          */
89         ret = ocsd_def_errlog_init(OCSD_ERR_SEV_ERROR, 1);
90         if (ret != 0)
91                 return -1;
92
93         /* no stdout / err / file output */
94         ret = ocsd_def_errlog_config_output(C_API_MSGLOGOUT_FLG_NONE, NULL);
95         if (ret != 0)
96                 return -1;
97
98         /*
99          * Set the string CB for the default logger, passes strings to
100          * perf print logger.
101          */
102         ret = ocsd_def_errlog_set_strprint_cb(decoder->dcd_tree,
103                                               (void *)decoder,
104                                               cs_etm_decoder__print_str_cb);
105         if (ret != 0)
106                 ret = -1;
107
108         return 0;
109 }
110
111 #ifdef CS_LOG_RAW_FRAMES
112 static void
113 cs_etm_decoder__init_raw_frame_logging(struct cs_etm_decoder_params *d_params,
114                                        struct cs_etm_decoder *decoder)
115 {
116         /* Only log these during a --dump operation */
117         if (d_params->operation == CS_ETM_OPERATION_PRINT) {
118                 /* set up a library default logger to process the
119                  *  raw frame printer we add later
120                  */
121                 ocsd_def_errlog_init(OCSD_ERR_SEV_ERROR, 1);
122
123                 /* no stdout / err / file output */
124                 ocsd_def_errlog_config_output(C_API_MSGLOGOUT_FLG_NONE, NULL);
125
126                 /* set the string CB for the default logger,
127                  * passes strings to perf print logger.
128                  */
129                 ocsd_def_errlog_set_strprint_cb(decoder->dcd_tree,
130                                                 (void *)decoder,
131                                                 cs_etm_decoder__print_str_cb);
132
133                 /* use the built in library printer for the raw frames */
134                 ocsd_dt_set_raw_frame_printer(decoder->dcd_tree,
135                                               CS_RAW_DEBUG_FLAGS);
136         }
137 }
138 #else
139 static void
140 cs_etm_decoder__init_raw_frame_logging(
141                 struct cs_etm_decoder_params *d_params __maybe_unused,
142                 struct cs_etm_decoder *decoder __maybe_unused)
143 {
144 }
145 #endif
146
147 static int cs_etm_decoder__create_packet_printer(struct cs_etm_decoder *decoder,
148                                                  const char *decoder_name,
149                                                  void *trace_config)
150 {
151         u8 csid;
152
153         if (ocsd_dt_create_decoder(decoder->dcd_tree, decoder_name,
154                                    OCSD_CREATE_FLG_PACKET_PROC,
155                                    trace_config, &csid))
156                 return -1;
157
158         if (ocsd_dt_set_pkt_protocol_printer(decoder->dcd_tree, csid, 0))
159                 return -1;
160
161         return 0;
162 }
163
164 static int
165 cs_etm_decoder__create_etm_packet_printer(struct cs_etm_trace_params *t_params,
166                                           struct cs_etm_decoder *decoder)
167 {
168         const char *decoder_name;
169         ocsd_etmv4_cfg trace_config_etmv4;
170         void *trace_config;
171
172         switch (t_params->protocol) {
173         case CS_ETM_PROTO_ETMV4i:
174                 cs_etm_decoder__gen_etmv4_config(t_params, &trace_config_etmv4);
175                 decoder_name = OCSD_BUILTIN_DCD_ETMV4I;
176                 trace_config = &trace_config_etmv4;
177                 break;
178         default:
179                 return -1;
180         }
181
182         return cs_etm_decoder__create_packet_printer(decoder,
183                                                      decoder_name,
184                                                      trace_config);
185 }
186
187 static void cs_etm_decoder__clear_buffer(struct cs_etm_decoder *decoder)
188 {
189         int i;
190
191         decoder->head = 0;
192         decoder->tail = 0;
193         decoder->packet_count = 0;
194         for (i = 0; i < MAX_BUFFER; i++) {
195                 decoder->packet_buffer[i].start_addr = 0xdeadbeefdeadbeefUL;
196                 decoder->packet_buffer[i].end_addr   = 0xdeadbeefdeadbeefUL;
197                 decoder->packet_buffer[i].exc        = false;
198                 decoder->packet_buffer[i].exc_ret    = false;
199                 decoder->packet_buffer[i].cpu        = INT_MIN;
200         }
201 }
202
203 static ocsd_datapath_resp_t
204 cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder,
205                               const ocsd_generic_trace_elem *elem,
206                               const u8 trace_chan_id,
207                               enum cs_etm_sample_type sample_type)
208 {
209         u32 et = 0;
210         struct int_node *inode = NULL;
211
212         if (decoder->packet_count >= MAX_BUFFER - 1)
213                 return OCSD_RESP_FATAL_SYS_ERR;
214
215         /* Search the RB tree for the cpu associated with this traceID */
216         inode = intlist__find(traceid_list, trace_chan_id);
217         if (!inode)
218                 return OCSD_RESP_FATAL_SYS_ERR;
219
220         et = decoder->tail;
221         decoder->packet_buffer[et].sample_type = sample_type;
222         decoder->packet_buffer[et].start_addr = elem->st_addr;
223         decoder->packet_buffer[et].end_addr = elem->en_addr;
224         decoder->packet_buffer[et].exc = false;
225         decoder->packet_buffer[et].exc_ret = false;
226         decoder->packet_buffer[et].cpu = *((int *)inode->priv);
227
228         /* Wrap around if need be */
229         et = (et + 1) & (MAX_BUFFER - 1);
230
231         decoder->tail = et;
232         decoder->packet_count++;
233
234         if (decoder->packet_count == MAX_BUFFER - 1)
235                 return OCSD_RESP_WAIT;
236
237         return OCSD_RESP_CONT;
238 }
239
240 static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer(
241                                 const void *context,
242                                 const ocsd_trc_index_t indx __maybe_unused,
243                                 const u8 trace_chan_id __maybe_unused,
244                                 const ocsd_generic_trace_elem *elem)
245 {
246         ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
247         struct cs_etm_decoder *decoder = (struct cs_etm_decoder *) context;
248
249         switch (elem->elem_type) {
250         case OCSD_GEN_TRC_ELEM_UNKNOWN:
251                 break;
252         case OCSD_GEN_TRC_ELEM_NO_SYNC:
253                 decoder->trace_on = false;
254                 break;
255         case OCSD_GEN_TRC_ELEM_TRACE_ON:
256                 decoder->trace_on = true;
257                 break;
258         case OCSD_GEN_TRC_ELEM_INSTR_RANGE:
259                 resp = cs_etm_decoder__buffer_packet(decoder, elem,
260                                                      trace_chan_id,
261                                                      CS_ETM_RANGE);
262                 break;
263         case OCSD_GEN_TRC_ELEM_EXCEPTION:
264                 decoder->packet_buffer[decoder->tail].exc = true;
265                 break;
266         case OCSD_GEN_TRC_ELEM_EXCEPTION_RET:
267                 decoder->packet_buffer[decoder->tail].exc_ret = true;
268                 break;
269         case OCSD_GEN_TRC_ELEM_PE_CONTEXT:
270         case OCSD_GEN_TRC_ELEM_EO_TRACE:
271         case OCSD_GEN_TRC_ELEM_ADDR_NACC:
272         case OCSD_GEN_TRC_ELEM_TIMESTAMP:
273         case OCSD_GEN_TRC_ELEM_CYCLE_COUNT:
274         case OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN:
275         case OCSD_GEN_TRC_ELEM_EVENT:
276         case OCSD_GEN_TRC_ELEM_SWTRACE:
277         case OCSD_GEN_TRC_ELEM_CUSTOM:
278         default:
279                 break;
280         }
281
282         return resp;
283 }
284
285 static int cs_etm_decoder__create_etm_packet_decoder(
286                                         struct cs_etm_trace_params *t_params,
287                                         struct cs_etm_decoder *decoder)
288 {
289         const char *decoder_name;
290         ocsd_etmv4_cfg trace_config_etmv4;
291         void *trace_config;
292         u8 csid;
293
294         switch (t_params->protocol) {
295         case CS_ETM_PROTO_ETMV4i:
296                 cs_etm_decoder__gen_etmv4_config(t_params, &trace_config_etmv4);
297                 decoder_name = OCSD_BUILTIN_DCD_ETMV4I;
298                 trace_config = &trace_config_etmv4;
299                 break;
300         default:
301                 return -1;
302         }
303
304         if (ocsd_dt_create_decoder(decoder->dcd_tree,
305                                      decoder_name,
306                                      OCSD_CREATE_FLG_FULL_DECODER,
307                                      trace_config, &csid))
308                 return -1;
309
310         if (ocsd_dt_set_gen_elem_outfn(decoder->dcd_tree,
311                                        cs_etm_decoder__gen_trace_elem_printer,
312                                        decoder))
313                 return -1;
314
315         return 0;
316 }
317
318 static int
319 cs_etm_decoder__create_etm_decoder(struct cs_etm_decoder_params *d_params,
320                                    struct cs_etm_trace_params *t_params,
321                                    struct cs_etm_decoder *decoder)
322 {
323         if (d_params->operation == CS_ETM_OPERATION_PRINT)
324                 return cs_etm_decoder__create_etm_packet_printer(t_params,
325                                                                  decoder);
326         else if (d_params->operation == CS_ETM_OPERATION_DECODE)
327                 return cs_etm_decoder__create_etm_packet_decoder(t_params,
328                                                                  decoder);
329
330         return -1;
331 }
332
333 struct cs_etm_decoder *
334 cs_etm_decoder__new(int num_cpu, struct cs_etm_decoder_params *d_params,
335                     struct cs_etm_trace_params t_params[])
336 {
337         struct cs_etm_decoder *decoder;
338         ocsd_dcd_tree_src_t format;
339         u32 flags;
340         int i, ret;
341
342         if ((!t_params) || (!d_params))
343                 return NULL;
344
345         decoder = zalloc(sizeof(*decoder));
346
347         if (!decoder)
348                 return NULL;
349
350         decoder->data = d_params->data;
351         decoder->prev_return = OCSD_RESP_CONT;
352         cs_etm_decoder__clear_buffer(decoder);
353         format = (d_params->formatted ? OCSD_TRC_SRC_FRAME_FORMATTED :
354                                          OCSD_TRC_SRC_SINGLE);
355         flags = 0;
356         flags |= (d_params->fsyncs ? OCSD_DFRMTR_HAS_FSYNCS : 0);
357         flags |= (d_params->hsyncs ? OCSD_DFRMTR_HAS_HSYNCS : 0);
358         flags |= (d_params->frame_aligned ? OCSD_DFRMTR_FRAME_MEM_ALIGN : 0);
359
360         /*
361          * Drivers may add barrier frames when used with perf, set up to
362          * handle this. Barriers const of FSYNC packet repeated 4 times.
363          */
364         flags |= OCSD_DFRMTR_RESET_ON_4X_FSYNC;
365
366         /* Create decode tree for the data source */
367         decoder->dcd_tree = ocsd_create_dcd_tree(format, flags);
368
369         if (decoder->dcd_tree == 0)
370                 goto err_free_decoder;
371
372         /* init library print logging support */
373         ret = cs_etm_decoder__init_def_logger_printing(d_params, decoder);
374         if (ret != 0)
375                 goto err_free_decoder_tree;
376
377         /* init raw frame logging if required */
378         cs_etm_decoder__init_raw_frame_logging(d_params, decoder);
379
380         for (i = 0; i < num_cpu; i++) {
381                 ret = cs_etm_decoder__create_etm_decoder(d_params,
382                                                          &t_params[i],
383                                                          decoder);
384                 if (ret != 0)
385                         goto err_free_decoder_tree;
386         }
387
388         return decoder;
389
390 err_free_decoder_tree:
391         ocsd_destroy_dcd_tree(decoder->dcd_tree);
392 err_free_decoder:
393         free(decoder);
394         return NULL;
395 }
396
397 int cs_etm_decoder__process_data_block(struct cs_etm_decoder *decoder,
398                                        u64 indx, const u8 *buf,
399                                        size_t len, size_t *consumed)
400 {
401         int ret = 0;
402         ocsd_datapath_resp_t cur = OCSD_RESP_CONT;
403         ocsd_datapath_resp_t prev_return = decoder->prev_return;
404         size_t processed = 0;
405         u32 count;
406
407         while (processed < len) {
408                 if (OCSD_DATA_RESP_IS_WAIT(prev_return)) {
409                         cur = ocsd_dt_process_data(decoder->dcd_tree,
410                                                    OCSD_OP_FLUSH,
411                                                    0,
412                                                    0,
413                                                    NULL,
414                                                    NULL);
415                 } else if (OCSD_DATA_RESP_IS_CONT(prev_return)) {
416                         cur = ocsd_dt_process_data(decoder->dcd_tree,
417                                                    OCSD_OP_DATA,
418                                                    indx + processed,
419                                                    len - processed,
420                                                    &buf[processed],
421                                                    &count);
422                         processed += count;
423                 } else {
424                         ret = -EINVAL;
425                         break;
426                 }
427
428                 /*
429                  * Return to the input code if the packet buffer is full.
430                  * Flushing will get done once the packet buffer has been
431                  * processed.
432                  */
433                 if (OCSD_DATA_RESP_IS_WAIT(cur))
434                         break;
435
436                 prev_return = cur;
437         }
438
439         decoder->prev_return = cur;
440         *consumed = processed;
441
442         return ret;
443 }
444
445 void cs_etm_decoder__free(struct cs_etm_decoder *decoder)
446 {
447         if (!decoder)
448                 return;
449
450         ocsd_destroy_dcd_tree(decoder->dcd_tree);
451         decoder->dcd_tree = NULL;
452         free(decoder);
453 }