1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright(C) 2015-2018 Linaro Limited.
4 *
5 * Author: Tor Jeremiassen <tor@ti.com>
6 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
7 */
8
9#include <linux/err.h>
10#include <linux/list.h>
11#include <linux/zalloc.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
21/* use raw logging */
22#ifdef CS_DEBUG_RAW
23#define CS_LOG_RAW_FRAMES
24#ifdef CS_RAW_PACKED
25#define CS_RAW_DEBUG_FLAGS (OCSD_DFRMTR_UNPACKED_RAW_OUT | \
26			    OCSD_DFRMTR_PACKED_RAW_OUT)
27#else
28#define CS_RAW_DEBUG_FLAGS (OCSD_DFRMTR_UNPACKED_RAW_OUT)
29#endif
30#endif
31
32struct cs_etm_decoder {
33	void *data;
34	void (*packet_printer)(const char *msg);
35	dcd_tree_handle_t dcd_tree;
36	cs_etm_mem_cb_type mem_access;
37	ocsd_datapath_resp_t prev_return;
38};
39
40static u32
41cs_etm_decoder__mem_access(const void *context,
42			   const ocsd_vaddr_t address,
43			   const ocsd_mem_space_acc_t mem_space __maybe_unused,
44			   const u8 trace_chan_id,
45			   const u32 req_size,
46			   u8 *buffer)
47{
48	struct cs_etm_decoder *decoder = (struct cs_etm_decoder *) context;
49
50	return decoder->mem_access(decoder->data, trace_chan_id,
51				   address, req_size, buffer);
52}
53
54int cs_etm_decoder__add_mem_access_cb(struct cs_etm_decoder *decoder,
55				      u64 start, u64 end,
56				      cs_etm_mem_cb_type cb_func)
57{
58	decoder->mem_access = cb_func;
59
60	if (ocsd_dt_add_callback_trcid_mem_acc(decoder->dcd_tree, start, end,
61					       OCSD_MEM_SPACE_ANY,
62					       cs_etm_decoder__mem_access,
63					       decoder))
64		return -1;
65
66	return 0;
67}
68
69int cs_etm_decoder__reset(struct cs_etm_decoder *decoder)
70{
71	ocsd_datapath_resp_t dp_ret;
72
73	decoder->prev_return = OCSD_RESP_CONT;
74
75	dp_ret = ocsd_dt_process_data(decoder->dcd_tree, OCSD_OP_RESET,
76				      0, 0, NULL, NULL);
77	if (OCSD_DATA_RESP_IS_FATAL(dp_ret))
78		return -1;
79
80	return 0;
81}
82
83int cs_etm_decoder__get_packet(struct cs_etm_packet_queue *packet_queue,
84			       struct cs_etm_packet *packet)
85{
86	if (!packet_queue || !packet)
87		return -EINVAL;
88
89	/* Nothing to do, might as well just return */
90	if (packet_queue->packet_count == 0)
91		return 0;
92	/*
93	 * The queueing process in function cs_etm_decoder__buffer_packet()
94	 * increments the tail *before* using it.  This is somewhat counter
95	 * intuitive but it has the advantage of centralizing tail management
96	 * at a single location.  Because of that we need to follow the same
97	 * heuristic with the head, i.e we increment it before using its
98	 * value.  Otherwise the first element of the packet queue is not
99	 * used.
100	 */
101	packet_queue->head = (packet_queue->head + 1) &
102			     (CS_ETM_PACKET_MAX_BUFFER - 1);
103
104	*packet = packet_queue->packet_buffer[packet_queue->head];
105
106	packet_queue->packet_count--;
107
108	return 1;
109}
110
111static int cs_etm_decoder__gen_etmv3_config(struct cs_etm_trace_params *params,
112					    ocsd_etmv3_cfg *config)
113{
114	config->reg_idr = params->etmv3.reg_idr;
115	config->reg_ctrl = params->etmv3.reg_ctrl;
116	config->reg_ccer = params->etmv3.reg_ccer;
117	config->reg_trc_id = params->etmv3.reg_trc_id;
118	config->arch_ver = ARCH_V7;
119	config->core_prof = profile_CortexA;
120
121	return 0;
122}
123
124static void cs_etm_decoder__gen_etmv4_config(struct cs_etm_trace_params *params,
125					     ocsd_etmv4_cfg *config)
126{
127	config->reg_configr = params->etmv4.reg_configr;
128	config->reg_traceidr = params->etmv4.reg_traceidr;
129	config->reg_idr0 = params->etmv4.reg_idr0;
130	config->reg_idr1 = params->etmv4.reg_idr1;
131	config->reg_idr2 = params->etmv4.reg_idr2;
132	config->reg_idr8 = params->etmv4.reg_idr8;
133	config->reg_idr9 = 0;
134	config->reg_idr10 = 0;
135	config->reg_idr11 = 0;
136	config->reg_idr12 = 0;
137	config->reg_idr13 = 0;
138	config->arch_ver = ARCH_V8;
139	config->core_prof = profile_CortexA;
140}
141
142static void cs_etm_decoder__print_str_cb(const void *p_context,
143					 const char *msg,
144					 const int str_len)
145{
146	if (p_context && str_len)
147		((struct cs_etm_decoder *)p_context)->packet_printer(msg);
148}
149
150static int
151cs_etm_decoder__init_def_logger_printing(struct cs_etm_decoder_params *d_params,
152					 struct cs_etm_decoder *decoder)
153{
154	int ret = 0;
155
156	if (d_params->packet_printer == NULL)
157		return -1;
158
159	decoder->packet_printer = d_params->packet_printer;
160
161	/*
162	 * Set up a library default logger to process any printers
163	 * (packet/raw frame) we add later.
164	 */
165	ret = ocsd_def_errlog_init(OCSD_ERR_SEV_ERROR, 1);
166	if (ret != 0)
167		return -1;
168
169	/* no stdout / err / file output */
170	ret = ocsd_def_errlog_config_output(C_API_MSGLOGOUT_FLG_NONE, NULL);
171	if (ret != 0)
172		return -1;
173
174	/*
175	 * Set the string CB for the default logger, passes strings to
176	 * perf print logger.
177	 */
178	ret = ocsd_def_errlog_set_strprint_cb(decoder->dcd_tree,
179					      (void *)decoder,
180					      cs_etm_decoder__print_str_cb);
181	if (ret != 0)
182		ret = -1;
183
184	return 0;
185}
186
187#ifdef CS_LOG_RAW_FRAMES
188static void
189cs_etm_decoder__init_raw_frame_logging(struct cs_etm_decoder_params *d_params,
190				       struct cs_etm_decoder *decoder)
191{
192	/* Only log these during a --dump operation */
193	if (d_params->operation == CS_ETM_OPERATION_PRINT) {
194		/* set up a library default logger to process the
195		 *  raw frame printer we add later
196		 */
197		ocsd_def_errlog_init(OCSD_ERR_SEV_ERROR, 1);
198
199		/* no stdout / err / file output */
200		ocsd_def_errlog_config_output(C_API_MSGLOGOUT_FLG_NONE, NULL);
201
202		/* set the string CB for the default logger,
203		 * passes strings to perf print logger.
204		 */
205		ocsd_def_errlog_set_strprint_cb(decoder->dcd_tree,
206						(void *)decoder,
207						cs_etm_decoder__print_str_cb);
208
209		/* use the built in library printer for the raw frames */
210		ocsd_dt_set_raw_frame_printer(decoder->dcd_tree,
211					      CS_RAW_DEBUG_FLAGS);
212	}
213}
214#else
215static void
216cs_etm_decoder__init_raw_frame_logging(
217		struct cs_etm_decoder_params *d_params __maybe_unused,
218		struct cs_etm_decoder *decoder __maybe_unused)
219{
220}
221#endif
222
223static int cs_etm_decoder__create_packet_printer(struct cs_etm_decoder *decoder,
224						 const char *decoder_name,
225						 void *trace_config)
226{
227	u8 csid;
228
229	if (ocsd_dt_create_decoder(decoder->dcd_tree, decoder_name,
230				   OCSD_CREATE_FLG_PACKET_PROC,
231				   trace_config, &csid))
232		return -1;
233
234	if (ocsd_dt_set_pkt_protocol_printer(decoder->dcd_tree, csid, 0))
235		return -1;
236
237	return 0;
238}
239
240static int
241cs_etm_decoder__create_etm_packet_printer(struct cs_etm_trace_params *t_params,
242					  struct cs_etm_decoder *decoder)
243{
244	const char *decoder_name;
245	ocsd_etmv3_cfg config_etmv3;
246	ocsd_etmv4_cfg trace_config_etmv4;
247	void *trace_config;
248
249	switch (t_params->protocol) {
250	case CS_ETM_PROTO_ETMV3:
251	case CS_ETM_PROTO_PTM:
252		cs_etm_decoder__gen_etmv3_config(t_params, &config_etmv3);
253		decoder_name = (t_params->protocol == CS_ETM_PROTO_ETMV3) ?
254							OCSD_BUILTIN_DCD_ETMV3 :
255							OCSD_BUILTIN_DCD_PTM;
256		trace_config = &config_etmv3;
257		break;
258	case CS_ETM_PROTO_ETMV4i:
259		cs_etm_decoder__gen_etmv4_config(t_params, &trace_config_etmv4);
260		decoder_name = OCSD_BUILTIN_DCD_ETMV4I;
261		trace_config = &trace_config_etmv4;
262		break;
263	default:
264		return -1;
265	}
266
267	return cs_etm_decoder__create_packet_printer(decoder,
268						     decoder_name,
269						     trace_config);
270}
271
272static ocsd_datapath_resp_t
273cs_etm_decoder__do_soft_timestamp(struct cs_etm_queue *etmq,
274				  struct cs_etm_packet_queue *packet_queue,
275				  const uint8_t trace_chan_id)
276{
277	/* No timestamp packet has been received, nothing to do */
278	if (!packet_queue->timestamp)
279		return OCSD_RESP_CONT;
280
281	packet_queue->timestamp = packet_queue->next_timestamp;
282
283	/* Estimate the timestamp for the next range packet */
284	packet_queue->next_timestamp += packet_queue->instr_count;
285	packet_queue->instr_count = 0;
286
287	/* Tell the front end which traceid_queue needs attention */
288	cs_etm__etmq_set_traceid_queue_timestamp(etmq, trace_chan_id);
289
290	return OCSD_RESP_WAIT;
291}
292
293static ocsd_datapath_resp_t
294cs_etm_decoder__do_hard_timestamp(struct cs_etm_queue *etmq,
295				  const ocsd_generic_trace_elem *elem,
296				  const uint8_t trace_chan_id)
297{
298	struct cs_etm_packet_queue *packet_queue;
299
300	/* First get the packet queue for this traceID */
301	packet_queue = cs_etm__etmq_get_packet_queue(etmq, trace_chan_id);
302	if (!packet_queue)
303		return OCSD_RESP_FATAL_SYS_ERR;
304
305	/*
306	 * We've seen a timestamp packet before - simply record the new value.
307	 * Function do_soft_timestamp() will report the value to the front end,
308	 * hence asking the decoder to keep decoding rather than stopping.
309	 */
310	if (packet_queue->timestamp) {
311		packet_queue->next_timestamp = elem->timestamp;
312		return OCSD_RESP_CONT;
313	}
314
315	/*
316	 * This is the first timestamp we've seen since the beginning of traces
317	 * or a discontinuity.  Since timestamps packets are generated *after*
318	 * range packets have been generated, we need to estimate the time at
319	 * which instructions started by substracting the number of instructions
320	 * executed to the timestamp.
321	 */
322	packet_queue->timestamp = elem->timestamp - packet_queue->instr_count;
323	packet_queue->next_timestamp = elem->timestamp;
324	packet_queue->instr_count = 0;
325
326	/* Tell the front end which traceid_queue needs attention */
327	cs_etm__etmq_set_traceid_queue_timestamp(etmq, trace_chan_id);
328
329	/* Halt processing until we are being told to proceed */
330	return OCSD_RESP_WAIT;
331}
332
333static void
334cs_etm_decoder__reset_timestamp(struct cs_etm_packet_queue *packet_queue)
335{
336	packet_queue->timestamp = 0;
337	packet_queue->next_timestamp = 0;
338	packet_queue->instr_count = 0;
339}
340
341static ocsd_datapath_resp_t
342cs_etm_decoder__buffer_packet(struct cs_etm_packet_queue *packet_queue,
343			      const u8 trace_chan_id,
344			      enum cs_etm_sample_type sample_type)
345{
346	u32 et = 0;
347	int cpu;
348
349	if (packet_queue->packet_count >= CS_ETM_PACKET_MAX_BUFFER - 1)
350		return OCSD_RESP_FATAL_SYS_ERR;
351
352	if (cs_etm__get_cpu(trace_chan_id, &cpu) < 0)
353		return OCSD_RESP_FATAL_SYS_ERR;
354
355	et = packet_queue->tail;
356	et = (et + 1) & (CS_ETM_PACKET_MAX_BUFFER - 1);
357	packet_queue->tail = et;
358	packet_queue->packet_count++;
359
360	packet_queue->packet_buffer[et].sample_type = sample_type;
361	packet_queue->packet_buffer[et].isa = CS_ETM_ISA_UNKNOWN;
362	packet_queue->packet_buffer[et].cpu = cpu;
363	packet_queue->packet_buffer[et].start_addr = CS_ETM_INVAL_ADDR;
364	packet_queue->packet_buffer[et].end_addr = CS_ETM_INVAL_ADDR;
365	packet_queue->packet_buffer[et].instr_count = 0;
366	packet_queue->packet_buffer[et].last_instr_taken_branch = false;
367	packet_queue->packet_buffer[et].last_instr_size = 0;
368	packet_queue->packet_buffer[et].last_instr_type = 0;
369	packet_queue->packet_buffer[et].last_instr_subtype = 0;
370	packet_queue->packet_buffer[et].last_instr_cond = 0;
371	packet_queue->packet_buffer[et].flags = 0;
372	packet_queue->packet_buffer[et].exception_number = UINT32_MAX;
373	packet_queue->packet_buffer[et].trace_chan_id = trace_chan_id;
374
375	if (packet_queue->packet_count == CS_ETM_PACKET_MAX_BUFFER - 1)
376		return OCSD_RESP_WAIT;
377
378	return OCSD_RESP_CONT;
379}
380
381static ocsd_datapath_resp_t
382cs_etm_decoder__buffer_range(struct cs_etm_queue *etmq,
383			     struct cs_etm_packet_queue *packet_queue,
384			     const ocsd_generic_trace_elem *elem,
385			     const uint8_t trace_chan_id)
386{
387	int ret = 0;
388	struct cs_etm_packet *packet;
389
390	ret = cs_etm_decoder__buffer_packet(packet_queue, trace_chan_id,
391					    CS_ETM_RANGE);
392	if (ret != OCSD_RESP_CONT && ret != OCSD_RESP_WAIT)
393		return ret;
394
395	packet = &packet_queue->packet_buffer[packet_queue->tail];
396
397	switch (elem->isa) {
398	case ocsd_isa_aarch64:
399		packet->isa = CS_ETM_ISA_A64;
400		break;
401	case ocsd_isa_arm:
402		packet->isa = CS_ETM_ISA_A32;
403		break;
404	case ocsd_isa_thumb2:
405		packet->isa = CS_ETM_ISA_T32;
406		break;
407	case ocsd_isa_tee:
408	case ocsd_isa_jazelle:
409	case ocsd_isa_custom:
410	case ocsd_isa_unknown:
411	default:
412		packet->isa = CS_ETM_ISA_UNKNOWN;
413	}
414
415	packet->start_addr = elem->st_addr;
416	packet->end_addr = elem->en_addr;
417	packet->instr_count = elem->num_instr_range;
418	packet->last_instr_type = elem->last_i_type;
419	packet->last_instr_subtype = elem->last_i_subtype;
420	packet->last_instr_cond = elem->last_instr_cond;
421
422	switch (elem->last_i_type) {
423	case OCSD_INSTR_BR:
424	case OCSD_INSTR_BR_INDIRECT:
425		packet->last_instr_taken_branch = elem->last_instr_exec;
426		break;
427	case OCSD_INSTR_ISB:
428	case OCSD_INSTR_DSB_DMB:
429	case OCSD_INSTR_WFI_WFE:
430	case OCSD_INSTR_OTHER:
431	default:
432		packet->last_instr_taken_branch = false;
433		break;
434	}
435
436	packet->last_instr_size = elem->last_instr_sz;
437
438	/* per-thread scenario, no need to generate a timestamp */
439	if (cs_etm__etmq_is_timeless(etmq))
440		goto out;
441
442	/*
443	 * The packet queue is full and we haven't seen a timestamp (had we
444	 * seen one the packet queue wouldn't be full).  Let the front end
445	 * deal with it.
446	 */
447	if (ret == OCSD_RESP_WAIT)
448		goto out;
449
450	packet_queue->instr_count += elem->num_instr_range;
451	/* Tell the front end we have a new timestamp to process */
452	ret = cs_etm_decoder__do_soft_timestamp(etmq, packet_queue,
453						trace_chan_id);
454out:
455	return ret;
456}
457
458static ocsd_datapath_resp_t
459cs_etm_decoder__buffer_discontinuity(struct cs_etm_packet_queue *queue,
460				     const uint8_t trace_chan_id)
461{
462	/*
463	 * Something happened and who knows when we'll get new traces so
464	 * reset time statistics.
465	 */
466	cs_etm_decoder__reset_timestamp(queue);
467	return cs_etm_decoder__buffer_packet(queue, trace_chan_id,
468					     CS_ETM_DISCONTINUITY);
469}
470
471static ocsd_datapath_resp_t
472cs_etm_decoder__buffer_exception(struct cs_etm_packet_queue *queue,
473				 const ocsd_generic_trace_elem *elem,
474				 const uint8_t trace_chan_id)
475{	int ret = 0;
476	struct cs_etm_packet *packet;
477
478	ret = cs_etm_decoder__buffer_packet(queue, trace_chan_id,
479					    CS_ETM_EXCEPTION);
480	if (ret != OCSD_RESP_CONT && ret != OCSD_RESP_WAIT)
481		return ret;
482
483	packet = &queue->packet_buffer[queue->tail];
484	packet->exception_number = elem->exception_number;
485
486	return ret;
487}
488
489static ocsd_datapath_resp_t
490cs_etm_decoder__buffer_exception_ret(struct cs_etm_packet_queue *queue,
491				     const uint8_t trace_chan_id)
492{
493	return cs_etm_decoder__buffer_packet(queue, trace_chan_id,
494					     CS_ETM_EXCEPTION_RET);
495}
496
497static ocsd_datapath_resp_t
498cs_etm_decoder__set_tid(struct cs_etm_queue *etmq,
499			struct cs_etm_packet_queue *packet_queue,
500			const ocsd_generic_trace_elem *elem,
501			const uint8_t trace_chan_id)
502{
503	pid_t tid;
504
505	/* Ignore PE_CONTEXT packets that don't have a valid contextID */
506	if (!elem->context.ctxt_id_valid)
507		return OCSD_RESP_CONT;
508
509	tid =  elem->context.context_id;
510	if (cs_etm__etmq_set_tid(etmq, tid, trace_chan_id))
511		return OCSD_RESP_FATAL_SYS_ERR;
512
513	/*
514	 * A timestamp is generated after a PE_CONTEXT element so make sure
515	 * to rely on that coming one.
516	 */
517	cs_etm_decoder__reset_timestamp(packet_queue);
518
519	return OCSD_RESP_CONT;
520}
521
522static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer(
523				const void *context,
524				const ocsd_trc_index_t indx __maybe_unused,
525				const u8 trace_chan_id __maybe_unused,
526				const ocsd_generic_trace_elem *elem)
527{
528	ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
529	struct cs_etm_decoder *decoder = (struct cs_etm_decoder *) context;
530	struct cs_etm_queue *etmq = decoder->data;
531	struct cs_etm_packet_queue *packet_queue;
532
533	/* First get the packet queue for this traceID */
534	packet_queue = cs_etm__etmq_get_packet_queue(etmq, trace_chan_id);
535	if (!packet_queue)
536		return OCSD_RESP_FATAL_SYS_ERR;
537
538	switch (elem->elem_type) {
539	case OCSD_GEN_TRC_ELEM_UNKNOWN:
540		break;
541	case OCSD_GEN_TRC_ELEM_EO_TRACE:
542	case OCSD_GEN_TRC_ELEM_NO_SYNC:
543	case OCSD_GEN_TRC_ELEM_TRACE_ON:
544		resp = cs_etm_decoder__buffer_discontinuity(packet_queue,
545							    trace_chan_id);
546		break;
547	case OCSD_GEN_TRC_ELEM_INSTR_RANGE:
548		resp = cs_etm_decoder__buffer_range(etmq, packet_queue, elem,
549						    trace_chan_id);
550		break;
551	case OCSD_GEN_TRC_ELEM_EXCEPTION:
552		resp = cs_etm_decoder__buffer_exception(packet_queue, elem,
553							trace_chan_id);
554		break;
555	case OCSD_GEN_TRC_ELEM_EXCEPTION_RET:
556		resp = cs_etm_decoder__buffer_exception_ret(packet_queue,
557							    trace_chan_id);
558		break;
559	case OCSD_GEN_TRC_ELEM_TIMESTAMP:
560		resp = cs_etm_decoder__do_hard_timestamp(etmq, elem,
561							 trace_chan_id);
562		break;
563	case OCSD_GEN_TRC_ELEM_PE_CONTEXT:
564		resp = cs_etm_decoder__set_tid(etmq, packet_queue,
565					       elem, trace_chan_id);
566		break;
567	/* Unused packet types */
568	case OCSD_GEN_TRC_ELEM_I_RANGE_NOPATH:
569	case OCSD_GEN_TRC_ELEM_ADDR_NACC:
570	case OCSD_GEN_TRC_ELEM_CYCLE_COUNT:
571	case OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN:
572	case OCSD_GEN_TRC_ELEM_EVENT:
573	case OCSD_GEN_TRC_ELEM_SWTRACE:
574	case OCSD_GEN_TRC_ELEM_CUSTOM:
575	default:
576		break;
577	}
578
579	return resp;
580}
581
582static int cs_etm_decoder__create_etm_packet_decoder(
583					struct cs_etm_trace_params *t_params,
584					struct cs_etm_decoder *decoder)
585{
586	const char *decoder_name;
587	ocsd_etmv3_cfg config_etmv3;
588	ocsd_etmv4_cfg trace_config_etmv4;
589	void *trace_config;
590	u8 csid;
591
592	switch (t_params->protocol) {
593	case CS_ETM_PROTO_ETMV3:
594	case CS_ETM_PROTO_PTM:
595		cs_etm_decoder__gen_etmv3_config(t_params, &config_etmv3);
596		decoder_name = (t_params->protocol == CS_ETM_PROTO_ETMV3) ?
597							OCSD_BUILTIN_DCD_ETMV3 :
598							OCSD_BUILTIN_DCD_PTM;
599		trace_config = &config_etmv3;
600		break;
601	case CS_ETM_PROTO_ETMV4i:
602		cs_etm_decoder__gen_etmv4_config(t_params, &trace_config_etmv4);
603		decoder_name = OCSD_BUILTIN_DCD_ETMV4I;
604		trace_config = &trace_config_etmv4;
605		break;
606	default:
607		return -1;
608	}
609
610	if (ocsd_dt_create_decoder(decoder->dcd_tree,
611				     decoder_name,
612				     OCSD_CREATE_FLG_FULL_DECODER,
613				     trace_config, &csid))
614		return -1;
615
616	if (ocsd_dt_set_gen_elem_outfn(decoder->dcd_tree,
617				       cs_etm_decoder__gen_trace_elem_printer,
618				       decoder))
619		return -1;
620
621	return 0;
622}
623
624static int
625cs_etm_decoder__create_etm_decoder(struct cs_etm_decoder_params *d_params,
626				   struct cs_etm_trace_params *t_params,
627				   struct cs_etm_decoder *decoder)
628{
629	if (d_params->operation == CS_ETM_OPERATION_PRINT)
630		return cs_etm_decoder__create_etm_packet_printer(t_params,
631								 decoder);
632	else if (d_params->operation == CS_ETM_OPERATION_DECODE)
633		return cs_etm_decoder__create_etm_packet_decoder(t_params,
634								 decoder);
635
636	return -1;
637}
638
639struct cs_etm_decoder *
640cs_etm_decoder__new(int num_cpu, struct cs_etm_decoder_params *d_params,
641		    struct cs_etm_trace_params t_params[])
642{
643	struct cs_etm_decoder *decoder;
644	ocsd_dcd_tree_src_t format;
645	u32 flags;
646	int i, ret;
647
648	if ((!t_params) || (!d_params))
649		return NULL;
650
651	decoder = zalloc(sizeof(*decoder));
652
653	if (!decoder)
654		return NULL;
655
656	decoder->data = d_params->data;
657	decoder->prev_return = OCSD_RESP_CONT;
658	format = (d_params->formatted ? OCSD_TRC_SRC_FRAME_FORMATTED :
659					 OCSD_TRC_SRC_SINGLE);
660	flags = 0;
661	flags |= (d_params->fsyncs ? OCSD_DFRMTR_HAS_FSYNCS : 0);
662	flags |= (d_params->hsyncs ? OCSD_DFRMTR_HAS_HSYNCS : 0);
663	flags |= (d_params->frame_aligned ? OCSD_DFRMTR_FRAME_MEM_ALIGN : 0);
664
665	/*
666	 * Drivers may add barrier frames when used with perf, set up to
667	 * handle this. Barriers const of FSYNC packet repeated 4 times.
668	 */
669	flags |= OCSD_DFRMTR_RESET_ON_4X_FSYNC;
670
671	/* Create decode tree for the data source */
672	decoder->dcd_tree = ocsd_create_dcd_tree(format, flags);
673
674	if (decoder->dcd_tree == 0)
675		goto err_free_decoder;
676
677	/* init library print logging support */
678	ret = cs_etm_decoder__init_def_logger_printing(d_params, decoder);
679	if (ret != 0)
680		goto err_free_decoder;
681
682	/* init raw frame logging if required */
683	cs_etm_decoder__init_raw_frame_logging(d_params, decoder);
684
685	for (i = 0; i < num_cpu; i++) {
686		ret = cs_etm_decoder__create_etm_decoder(d_params,
687							 &t_params[i],
688							 decoder);
689		if (ret != 0)
690			goto err_free_decoder;
691	}
692
693	return decoder;
694
695err_free_decoder:
696	cs_etm_decoder__free(decoder);
697	return NULL;
698}
699
700int cs_etm_decoder__process_data_block(struct cs_etm_decoder *decoder,
701				       u64 indx, const u8 *buf,
702				       size_t len, size_t *consumed)
703{
704	int ret = 0;
705	ocsd_datapath_resp_t cur = OCSD_RESP_CONT;
706	ocsd_datapath_resp_t prev_return = decoder->prev_return;
707	size_t processed = 0;
708	u32 count;
709
710	while (processed < len) {
711		if (OCSD_DATA_RESP_IS_WAIT(prev_return)) {
712			cur = ocsd_dt_process_data(decoder->dcd_tree,
713						   OCSD_OP_FLUSH,
714						   0,
715						   0,
716						   NULL,
717						   NULL);
718		} else if (OCSD_DATA_RESP_IS_CONT(prev_return)) {
719			cur = ocsd_dt_process_data(decoder->dcd_tree,
720						   OCSD_OP_DATA,
721						   indx + processed,
722						   len - processed,
723						   &buf[processed],
724						   &count);
725			processed += count;
726		} else {
727			ret = -EINVAL;
728			break;
729		}
730
731		/*
732		 * Return to the input code if the packet buffer is full.
733		 * Flushing will get done once the packet buffer has been
734		 * processed.
735		 */
736		if (OCSD_DATA_RESP_IS_WAIT(cur))
737			break;
738
739		prev_return = cur;
740	}
741
742	decoder->prev_return = cur;
743	*consumed = processed;
744
745	return ret;
746}
747
748void cs_etm_decoder__free(struct cs_etm_decoder *decoder)
749{
750	if (!decoder)
751		return;
752
753	ocsd_destroy_dcd_tree(decoder->dcd_tree);
754	decoder->dcd_tree = NULL;
755	free(decoder);
756}
757