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