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