xref: /OK3568_Linux_fs/kernel/tools/perf/util/cs-etm.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright(C) 2015-2018 Linaro Limited.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Author: Tor Jeremiassen <tor@ti.com>
6*4882a593Smuzhiyun  * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #include <linux/bitops.h>
10*4882a593Smuzhiyun #include <linux/err.h>
11*4882a593Smuzhiyun #include <linux/kernel.h>
12*4882a593Smuzhiyun #include <linux/log2.h>
13*4882a593Smuzhiyun #include <linux/types.h>
14*4882a593Smuzhiyun #include <linux/zalloc.h>
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #include <opencsd/ocsd_if_types.h>
17*4882a593Smuzhiyun #include <stdlib.h>
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #include "auxtrace.h"
20*4882a593Smuzhiyun #include "color.h"
21*4882a593Smuzhiyun #include "cs-etm.h"
22*4882a593Smuzhiyun #include "cs-etm-decoder/cs-etm-decoder.h"
23*4882a593Smuzhiyun #include "debug.h"
24*4882a593Smuzhiyun #include "dso.h"
25*4882a593Smuzhiyun #include "evlist.h"
26*4882a593Smuzhiyun #include "intlist.h"
27*4882a593Smuzhiyun #include "machine.h"
28*4882a593Smuzhiyun #include "map.h"
29*4882a593Smuzhiyun #include "perf.h"
30*4882a593Smuzhiyun #include "session.h"
31*4882a593Smuzhiyun #include "map_symbol.h"
32*4882a593Smuzhiyun #include "branch.h"
33*4882a593Smuzhiyun #include "symbol.h"
34*4882a593Smuzhiyun #include "tool.h"
35*4882a593Smuzhiyun #include "thread.h"
36*4882a593Smuzhiyun #include "thread-stack.h"
37*4882a593Smuzhiyun #include <tools/libc_compat.h>
38*4882a593Smuzhiyun #include "util/synthetic-events.h"
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun #define MAX_TIMESTAMP (~0ULL)
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun struct cs_etm_auxtrace {
43*4882a593Smuzhiyun 	struct auxtrace auxtrace;
44*4882a593Smuzhiyun 	struct auxtrace_queues queues;
45*4882a593Smuzhiyun 	struct auxtrace_heap heap;
46*4882a593Smuzhiyun 	struct itrace_synth_opts synth_opts;
47*4882a593Smuzhiyun 	struct perf_session *session;
48*4882a593Smuzhiyun 	struct machine *machine;
49*4882a593Smuzhiyun 	struct thread *unknown_thread;
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	u8 timeless_decoding;
52*4882a593Smuzhiyun 	u8 snapshot_mode;
53*4882a593Smuzhiyun 	u8 data_queued;
54*4882a593Smuzhiyun 	u8 sample_branches;
55*4882a593Smuzhiyun 	u8 sample_instructions;
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	int num_cpu;
58*4882a593Smuzhiyun 	u32 auxtrace_type;
59*4882a593Smuzhiyun 	u64 branches_sample_type;
60*4882a593Smuzhiyun 	u64 branches_id;
61*4882a593Smuzhiyun 	u64 instructions_sample_type;
62*4882a593Smuzhiyun 	u64 instructions_sample_period;
63*4882a593Smuzhiyun 	u64 instructions_id;
64*4882a593Smuzhiyun 	u64 **metadata;
65*4882a593Smuzhiyun 	u64 kernel_start;
66*4882a593Smuzhiyun 	unsigned int pmu_type;
67*4882a593Smuzhiyun };
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun struct cs_etm_traceid_queue {
70*4882a593Smuzhiyun 	u8 trace_chan_id;
71*4882a593Smuzhiyun 	pid_t pid, tid;
72*4882a593Smuzhiyun 	u64 period_instructions;
73*4882a593Smuzhiyun 	size_t last_branch_pos;
74*4882a593Smuzhiyun 	union perf_event *event_buf;
75*4882a593Smuzhiyun 	struct thread *thread;
76*4882a593Smuzhiyun 	struct branch_stack *last_branch;
77*4882a593Smuzhiyun 	struct branch_stack *last_branch_rb;
78*4882a593Smuzhiyun 	struct cs_etm_packet *prev_packet;
79*4882a593Smuzhiyun 	struct cs_etm_packet *packet;
80*4882a593Smuzhiyun 	struct cs_etm_packet_queue packet_queue;
81*4882a593Smuzhiyun };
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun struct cs_etm_queue {
84*4882a593Smuzhiyun 	struct cs_etm_auxtrace *etm;
85*4882a593Smuzhiyun 	struct cs_etm_decoder *decoder;
86*4882a593Smuzhiyun 	struct auxtrace_buffer *buffer;
87*4882a593Smuzhiyun 	unsigned int queue_nr;
88*4882a593Smuzhiyun 	u8 pending_timestamp;
89*4882a593Smuzhiyun 	u64 offset;
90*4882a593Smuzhiyun 	const unsigned char *buf;
91*4882a593Smuzhiyun 	size_t buf_len, buf_used;
92*4882a593Smuzhiyun 	/* Conversion between traceID and index in traceid_queues array */
93*4882a593Smuzhiyun 	struct intlist *traceid_queues_list;
94*4882a593Smuzhiyun 	struct cs_etm_traceid_queue **traceid_queues;
95*4882a593Smuzhiyun };
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun /* RB tree for quick conversion between traceID and metadata pointers */
98*4882a593Smuzhiyun static struct intlist *traceid_list;
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun static int cs_etm__update_queues(struct cs_etm_auxtrace *etm);
101*4882a593Smuzhiyun static int cs_etm__process_queues(struct cs_etm_auxtrace *etm);
102*4882a593Smuzhiyun static int cs_etm__process_timeless_queues(struct cs_etm_auxtrace *etm,
103*4882a593Smuzhiyun 					   pid_t tid);
104*4882a593Smuzhiyun static int cs_etm__get_data_block(struct cs_etm_queue *etmq);
105*4882a593Smuzhiyun static int cs_etm__decode_data_block(struct cs_etm_queue *etmq);
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun /* PTMs ETMIDR [11:8] set to b0011 */
108*4882a593Smuzhiyun #define ETMIDR_PTM_VERSION 0x00000300
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun /*
111*4882a593Smuzhiyun  * A struct auxtrace_heap_item only has a queue_nr and a timestamp to
112*4882a593Smuzhiyun  * work with.  One option is to modify to auxtrace_heap_XYZ() API or simply
113*4882a593Smuzhiyun  * encode the etm queue number as the upper 16 bit and the channel as
114*4882a593Smuzhiyun  * the lower 16 bit.
115*4882a593Smuzhiyun  */
116*4882a593Smuzhiyun #define TO_CS_QUEUE_NR(queue_nr, trace_chan_id)	\
117*4882a593Smuzhiyun 		      (queue_nr << 16 | trace_chan_id)
118*4882a593Smuzhiyun #define TO_QUEUE_NR(cs_queue_nr) (cs_queue_nr >> 16)
119*4882a593Smuzhiyun #define TO_TRACE_CHAN_ID(cs_queue_nr) (cs_queue_nr & 0x0000ffff)
120*4882a593Smuzhiyun 
cs_etm__get_v7_protocol_version(u32 etmidr)121*4882a593Smuzhiyun static u32 cs_etm__get_v7_protocol_version(u32 etmidr)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun 	etmidr &= ETMIDR_PTM_VERSION;
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	if (etmidr == ETMIDR_PTM_VERSION)
126*4882a593Smuzhiyun 		return CS_ETM_PROTO_PTM;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	return CS_ETM_PROTO_ETMV3;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun 
cs_etm__get_magic(u8 trace_chan_id,u64 * magic)131*4882a593Smuzhiyun static int cs_etm__get_magic(u8 trace_chan_id, u64 *magic)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun 	struct int_node *inode;
134*4882a593Smuzhiyun 	u64 *metadata;
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	inode = intlist__find(traceid_list, trace_chan_id);
137*4882a593Smuzhiyun 	if (!inode)
138*4882a593Smuzhiyun 		return -EINVAL;
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 	metadata = inode->priv;
141*4882a593Smuzhiyun 	*magic = metadata[CS_ETM_MAGIC];
142*4882a593Smuzhiyun 	return 0;
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun 
cs_etm__get_cpu(u8 trace_chan_id,int * cpu)145*4882a593Smuzhiyun int cs_etm__get_cpu(u8 trace_chan_id, int *cpu)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun 	struct int_node *inode;
148*4882a593Smuzhiyun 	u64 *metadata;
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	inode = intlist__find(traceid_list, trace_chan_id);
151*4882a593Smuzhiyun 	if (!inode)
152*4882a593Smuzhiyun 		return -EINVAL;
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	metadata = inode->priv;
155*4882a593Smuzhiyun 	*cpu = (int)metadata[CS_ETM_CPU];
156*4882a593Smuzhiyun 	return 0;
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun 
cs_etm__etmq_set_traceid_queue_timestamp(struct cs_etm_queue * etmq,u8 trace_chan_id)159*4882a593Smuzhiyun void cs_etm__etmq_set_traceid_queue_timestamp(struct cs_etm_queue *etmq,
160*4882a593Smuzhiyun 					      u8 trace_chan_id)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun 	/*
163*4882a593Smuzhiyun 	 * Wnen a timestamp packet is encountered the backend code
164*4882a593Smuzhiyun 	 * is stopped so that the front end has time to process packets
165*4882a593Smuzhiyun 	 * that were accumulated in the traceID queue.  Since there can
166*4882a593Smuzhiyun 	 * be more than one channel per cs_etm_queue, we need to specify
167*4882a593Smuzhiyun 	 * what traceID queue needs servicing.
168*4882a593Smuzhiyun 	 */
169*4882a593Smuzhiyun 	etmq->pending_timestamp = trace_chan_id;
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun 
cs_etm__etmq_get_timestamp(struct cs_etm_queue * etmq,u8 * trace_chan_id)172*4882a593Smuzhiyun static u64 cs_etm__etmq_get_timestamp(struct cs_etm_queue *etmq,
173*4882a593Smuzhiyun 				      u8 *trace_chan_id)
174*4882a593Smuzhiyun {
175*4882a593Smuzhiyun 	struct cs_etm_packet_queue *packet_queue;
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	if (!etmq->pending_timestamp)
178*4882a593Smuzhiyun 		return 0;
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	if (trace_chan_id)
181*4882a593Smuzhiyun 		*trace_chan_id = etmq->pending_timestamp;
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	packet_queue = cs_etm__etmq_get_packet_queue(etmq,
184*4882a593Smuzhiyun 						     etmq->pending_timestamp);
185*4882a593Smuzhiyun 	if (!packet_queue)
186*4882a593Smuzhiyun 		return 0;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	/* Acknowledge pending status */
189*4882a593Smuzhiyun 	etmq->pending_timestamp = 0;
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	/* See function cs_etm_decoder__do_{hard|soft}_timestamp() */
192*4882a593Smuzhiyun 	return packet_queue->timestamp;
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun 
cs_etm__clear_packet_queue(struct cs_etm_packet_queue * queue)195*4882a593Smuzhiyun static void cs_etm__clear_packet_queue(struct cs_etm_packet_queue *queue)
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun 	int i;
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	queue->head = 0;
200*4882a593Smuzhiyun 	queue->tail = 0;
201*4882a593Smuzhiyun 	queue->packet_count = 0;
202*4882a593Smuzhiyun 	for (i = 0; i < CS_ETM_PACKET_MAX_BUFFER; i++) {
203*4882a593Smuzhiyun 		queue->packet_buffer[i].isa = CS_ETM_ISA_UNKNOWN;
204*4882a593Smuzhiyun 		queue->packet_buffer[i].start_addr = CS_ETM_INVAL_ADDR;
205*4882a593Smuzhiyun 		queue->packet_buffer[i].end_addr = CS_ETM_INVAL_ADDR;
206*4882a593Smuzhiyun 		queue->packet_buffer[i].instr_count = 0;
207*4882a593Smuzhiyun 		queue->packet_buffer[i].last_instr_taken_branch = false;
208*4882a593Smuzhiyun 		queue->packet_buffer[i].last_instr_size = 0;
209*4882a593Smuzhiyun 		queue->packet_buffer[i].last_instr_type = 0;
210*4882a593Smuzhiyun 		queue->packet_buffer[i].last_instr_subtype = 0;
211*4882a593Smuzhiyun 		queue->packet_buffer[i].last_instr_cond = 0;
212*4882a593Smuzhiyun 		queue->packet_buffer[i].flags = 0;
213*4882a593Smuzhiyun 		queue->packet_buffer[i].exception_number = UINT32_MAX;
214*4882a593Smuzhiyun 		queue->packet_buffer[i].trace_chan_id = UINT8_MAX;
215*4882a593Smuzhiyun 		queue->packet_buffer[i].cpu = INT_MIN;
216*4882a593Smuzhiyun 	}
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun 
cs_etm__clear_all_packet_queues(struct cs_etm_queue * etmq)219*4882a593Smuzhiyun static void cs_etm__clear_all_packet_queues(struct cs_etm_queue *etmq)
220*4882a593Smuzhiyun {
221*4882a593Smuzhiyun 	int idx;
222*4882a593Smuzhiyun 	struct int_node *inode;
223*4882a593Smuzhiyun 	struct cs_etm_traceid_queue *tidq;
224*4882a593Smuzhiyun 	struct intlist *traceid_queues_list = etmq->traceid_queues_list;
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	intlist__for_each_entry(inode, traceid_queues_list) {
227*4882a593Smuzhiyun 		idx = (int)(intptr_t)inode->priv;
228*4882a593Smuzhiyun 		tidq = etmq->traceid_queues[idx];
229*4882a593Smuzhiyun 		cs_etm__clear_packet_queue(&tidq->packet_queue);
230*4882a593Smuzhiyun 	}
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun 
cs_etm__init_traceid_queue(struct cs_etm_queue * etmq,struct cs_etm_traceid_queue * tidq,u8 trace_chan_id)233*4882a593Smuzhiyun static int cs_etm__init_traceid_queue(struct cs_etm_queue *etmq,
234*4882a593Smuzhiyun 				      struct cs_etm_traceid_queue *tidq,
235*4882a593Smuzhiyun 				      u8 trace_chan_id)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun 	int rc = -ENOMEM;
238*4882a593Smuzhiyun 	struct auxtrace_queue *queue;
239*4882a593Smuzhiyun 	struct cs_etm_auxtrace *etm = etmq->etm;
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	cs_etm__clear_packet_queue(&tidq->packet_queue);
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	queue = &etmq->etm->queues.queue_array[etmq->queue_nr];
244*4882a593Smuzhiyun 	tidq->tid = queue->tid;
245*4882a593Smuzhiyun 	tidq->pid = -1;
246*4882a593Smuzhiyun 	tidq->trace_chan_id = trace_chan_id;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	tidq->packet = zalloc(sizeof(struct cs_etm_packet));
249*4882a593Smuzhiyun 	if (!tidq->packet)
250*4882a593Smuzhiyun 		goto out;
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	tidq->prev_packet = zalloc(sizeof(struct cs_etm_packet));
253*4882a593Smuzhiyun 	if (!tidq->prev_packet)
254*4882a593Smuzhiyun 		goto out_free;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	if (etm->synth_opts.last_branch) {
257*4882a593Smuzhiyun 		size_t sz = sizeof(struct branch_stack);
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 		sz += etm->synth_opts.last_branch_sz *
260*4882a593Smuzhiyun 		      sizeof(struct branch_entry);
261*4882a593Smuzhiyun 		tidq->last_branch = zalloc(sz);
262*4882a593Smuzhiyun 		if (!tidq->last_branch)
263*4882a593Smuzhiyun 			goto out_free;
264*4882a593Smuzhiyun 		tidq->last_branch_rb = zalloc(sz);
265*4882a593Smuzhiyun 		if (!tidq->last_branch_rb)
266*4882a593Smuzhiyun 			goto out_free;
267*4882a593Smuzhiyun 	}
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 	tidq->event_buf = malloc(PERF_SAMPLE_MAX_SIZE);
270*4882a593Smuzhiyun 	if (!tidq->event_buf)
271*4882a593Smuzhiyun 		goto out_free;
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	return 0;
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun out_free:
276*4882a593Smuzhiyun 	zfree(&tidq->last_branch_rb);
277*4882a593Smuzhiyun 	zfree(&tidq->last_branch);
278*4882a593Smuzhiyun 	zfree(&tidq->prev_packet);
279*4882a593Smuzhiyun 	zfree(&tidq->packet);
280*4882a593Smuzhiyun out:
281*4882a593Smuzhiyun 	return rc;
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun static struct cs_etm_traceid_queue
cs_etm__etmq_get_traceid_queue(struct cs_etm_queue * etmq,u8 trace_chan_id)285*4882a593Smuzhiyun *cs_etm__etmq_get_traceid_queue(struct cs_etm_queue *etmq, u8 trace_chan_id)
286*4882a593Smuzhiyun {
287*4882a593Smuzhiyun 	int idx;
288*4882a593Smuzhiyun 	struct int_node *inode;
289*4882a593Smuzhiyun 	struct intlist *traceid_queues_list;
290*4882a593Smuzhiyun 	struct cs_etm_traceid_queue *tidq, **traceid_queues;
291*4882a593Smuzhiyun 	struct cs_etm_auxtrace *etm = etmq->etm;
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	if (etm->timeless_decoding)
294*4882a593Smuzhiyun 		trace_chan_id = CS_ETM_PER_THREAD_TRACEID;
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	traceid_queues_list = etmq->traceid_queues_list;
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 	/*
299*4882a593Smuzhiyun 	 * Check if the traceid_queue exist for this traceID by looking
300*4882a593Smuzhiyun 	 * in the queue list.
301*4882a593Smuzhiyun 	 */
302*4882a593Smuzhiyun 	inode = intlist__find(traceid_queues_list, trace_chan_id);
303*4882a593Smuzhiyun 	if (inode) {
304*4882a593Smuzhiyun 		idx = (int)(intptr_t)inode->priv;
305*4882a593Smuzhiyun 		return etmq->traceid_queues[idx];
306*4882a593Smuzhiyun 	}
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	/* We couldn't find a traceid_queue for this traceID, allocate one */
309*4882a593Smuzhiyun 	tidq = malloc(sizeof(*tidq));
310*4882a593Smuzhiyun 	if (!tidq)
311*4882a593Smuzhiyun 		return NULL;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	memset(tidq, 0, sizeof(*tidq));
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 	/* Get a valid index for the new traceid_queue */
316*4882a593Smuzhiyun 	idx = intlist__nr_entries(traceid_queues_list);
317*4882a593Smuzhiyun 	/* Memory for the inode is free'ed in cs_etm_free_traceid_queues () */
318*4882a593Smuzhiyun 	inode = intlist__findnew(traceid_queues_list, trace_chan_id);
319*4882a593Smuzhiyun 	if (!inode)
320*4882a593Smuzhiyun 		goto out_free;
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	/* Associate this traceID with this index */
323*4882a593Smuzhiyun 	inode->priv = (void *)(intptr_t)idx;
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	if (cs_etm__init_traceid_queue(etmq, tidq, trace_chan_id))
326*4882a593Smuzhiyun 		goto out_free;
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 	/* Grow the traceid_queues array by one unit */
329*4882a593Smuzhiyun 	traceid_queues = etmq->traceid_queues;
330*4882a593Smuzhiyun 	traceid_queues = reallocarray(traceid_queues,
331*4882a593Smuzhiyun 				      idx + 1,
332*4882a593Smuzhiyun 				      sizeof(*traceid_queues));
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	/*
335*4882a593Smuzhiyun 	 * On failure reallocarray() returns NULL and the original block of
336*4882a593Smuzhiyun 	 * memory is left untouched.
337*4882a593Smuzhiyun 	 */
338*4882a593Smuzhiyun 	if (!traceid_queues)
339*4882a593Smuzhiyun 		goto out_free;
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 	traceid_queues[idx] = tidq;
342*4882a593Smuzhiyun 	etmq->traceid_queues = traceid_queues;
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 	return etmq->traceid_queues[idx];
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun out_free:
347*4882a593Smuzhiyun 	/*
348*4882a593Smuzhiyun 	 * Function intlist__remove() removes the inode from the list
349*4882a593Smuzhiyun 	 * and delete the memory associated to it.
350*4882a593Smuzhiyun 	 */
351*4882a593Smuzhiyun 	intlist__remove(traceid_queues_list, inode);
352*4882a593Smuzhiyun 	free(tidq);
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	return NULL;
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun struct cs_etm_packet_queue
cs_etm__etmq_get_packet_queue(struct cs_etm_queue * etmq,u8 trace_chan_id)358*4882a593Smuzhiyun *cs_etm__etmq_get_packet_queue(struct cs_etm_queue *etmq, u8 trace_chan_id)
359*4882a593Smuzhiyun {
360*4882a593Smuzhiyun 	struct cs_etm_traceid_queue *tidq;
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun 	tidq = cs_etm__etmq_get_traceid_queue(etmq, trace_chan_id);
363*4882a593Smuzhiyun 	if (tidq)
364*4882a593Smuzhiyun 		return &tidq->packet_queue;
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun 	return NULL;
367*4882a593Smuzhiyun }
368*4882a593Smuzhiyun 
cs_etm__packet_swap(struct cs_etm_auxtrace * etm,struct cs_etm_traceid_queue * tidq)369*4882a593Smuzhiyun static void cs_etm__packet_swap(struct cs_etm_auxtrace *etm,
370*4882a593Smuzhiyun 				struct cs_etm_traceid_queue *tidq)
371*4882a593Smuzhiyun {
372*4882a593Smuzhiyun 	struct cs_etm_packet *tmp;
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	if (etm->sample_branches || etm->synth_opts.last_branch ||
375*4882a593Smuzhiyun 	    etm->sample_instructions) {
376*4882a593Smuzhiyun 		/*
377*4882a593Smuzhiyun 		 * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
378*4882a593Smuzhiyun 		 * the next incoming packet.
379*4882a593Smuzhiyun 		 */
380*4882a593Smuzhiyun 		tmp = tidq->packet;
381*4882a593Smuzhiyun 		tidq->packet = tidq->prev_packet;
382*4882a593Smuzhiyun 		tidq->prev_packet = tmp;
383*4882a593Smuzhiyun 	}
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun 
cs_etm__packet_dump(const char * pkt_string)386*4882a593Smuzhiyun static void cs_etm__packet_dump(const char *pkt_string)
387*4882a593Smuzhiyun {
388*4882a593Smuzhiyun 	const char *color = PERF_COLOR_BLUE;
389*4882a593Smuzhiyun 	int len = strlen(pkt_string);
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun 	if (len && (pkt_string[len-1] == '\n'))
392*4882a593Smuzhiyun 		color_fprintf(stdout, color, "	%s", pkt_string);
393*4882a593Smuzhiyun 	else
394*4882a593Smuzhiyun 		color_fprintf(stdout, color, "	%s\n", pkt_string);
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 	fflush(stdout);
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun 
cs_etm__set_trace_param_etmv3(struct cs_etm_trace_params * t_params,struct cs_etm_auxtrace * etm,int idx,u32 etmidr)399*4882a593Smuzhiyun static void cs_etm__set_trace_param_etmv3(struct cs_etm_trace_params *t_params,
400*4882a593Smuzhiyun 					  struct cs_etm_auxtrace *etm, int idx,
401*4882a593Smuzhiyun 					  u32 etmidr)
402*4882a593Smuzhiyun {
403*4882a593Smuzhiyun 	u64 **metadata = etm->metadata;
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 	t_params[idx].protocol = cs_etm__get_v7_protocol_version(etmidr);
406*4882a593Smuzhiyun 	t_params[idx].etmv3.reg_ctrl = metadata[idx][CS_ETM_ETMCR];
407*4882a593Smuzhiyun 	t_params[idx].etmv3.reg_trc_id = metadata[idx][CS_ETM_ETMTRACEIDR];
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun 
cs_etm__set_trace_param_etmv4(struct cs_etm_trace_params * t_params,struct cs_etm_auxtrace * etm,int idx)410*4882a593Smuzhiyun static void cs_etm__set_trace_param_etmv4(struct cs_etm_trace_params *t_params,
411*4882a593Smuzhiyun 					  struct cs_etm_auxtrace *etm, int idx)
412*4882a593Smuzhiyun {
413*4882a593Smuzhiyun 	u64 **metadata = etm->metadata;
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 	t_params[idx].protocol = CS_ETM_PROTO_ETMV4i;
416*4882a593Smuzhiyun 	t_params[idx].etmv4.reg_idr0 = metadata[idx][CS_ETMV4_TRCIDR0];
417*4882a593Smuzhiyun 	t_params[idx].etmv4.reg_idr1 = metadata[idx][CS_ETMV4_TRCIDR1];
418*4882a593Smuzhiyun 	t_params[idx].etmv4.reg_idr2 = metadata[idx][CS_ETMV4_TRCIDR2];
419*4882a593Smuzhiyun 	t_params[idx].etmv4.reg_idr8 = metadata[idx][CS_ETMV4_TRCIDR8];
420*4882a593Smuzhiyun 	t_params[idx].etmv4.reg_configr = metadata[idx][CS_ETMV4_TRCCONFIGR];
421*4882a593Smuzhiyun 	t_params[idx].etmv4.reg_traceidr = metadata[idx][CS_ETMV4_TRCTRACEIDR];
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun 
cs_etm__init_trace_params(struct cs_etm_trace_params * t_params,struct cs_etm_auxtrace * etm)424*4882a593Smuzhiyun static int cs_etm__init_trace_params(struct cs_etm_trace_params *t_params,
425*4882a593Smuzhiyun 				     struct cs_etm_auxtrace *etm)
426*4882a593Smuzhiyun {
427*4882a593Smuzhiyun 	int i;
428*4882a593Smuzhiyun 	u32 etmidr;
429*4882a593Smuzhiyun 	u64 architecture;
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun 	for (i = 0; i < etm->num_cpu; i++) {
432*4882a593Smuzhiyun 		architecture = etm->metadata[i][CS_ETM_MAGIC];
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun 		switch (architecture) {
435*4882a593Smuzhiyun 		case __perf_cs_etmv3_magic:
436*4882a593Smuzhiyun 			etmidr = etm->metadata[i][CS_ETM_ETMIDR];
437*4882a593Smuzhiyun 			cs_etm__set_trace_param_etmv3(t_params, etm, i, etmidr);
438*4882a593Smuzhiyun 			break;
439*4882a593Smuzhiyun 		case __perf_cs_etmv4_magic:
440*4882a593Smuzhiyun 			cs_etm__set_trace_param_etmv4(t_params, etm, i);
441*4882a593Smuzhiyun 			break;
442*4882a593Smuzhiyun 		default:
443*4882a593Smuzhiyun 			return -EINVAL;
444*4882a593Smuzhiyun 		}
445*4882a593Smuzhiyun 	}
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	return 0;
448*4882a593Smuzhiyun }
449*4882a593Smuzhiyun 
cs_etm__init_decoder_params(struct cs_etm_decoder_params * d_params,struct cs_etm_queue * etmq,enum cs_etm_decoder_operation mode)450*4882a593Smuzhiyun static int cs_etm__init_decoder_params(struct cs_etm_decoder_params *d_params,
451*4882a593Smuzhiyun 				       struct cs_etm_queue *etmq,
452*4882a593Smuzhiyun 				       enum cs_etm_decoder_operation mode)
453*4882a593Smuzhiyun {
454*4882a593Smuzhiyun 	int ret = -EINVAL;
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun 	if (!(mode < CS_ETM_OPERATION_MAX))
457*4882a593Smuzhiyun 		goto out;
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 	d_params->packet_printer = cs_etm__packet_dump;
460*4882a593Smuzhiyun 	d_params->operation = mode;
461*4882a593Smuzhiyun 	d_params->data = etmq;
462*4882a593Smuzhiyun 	d_params->formatted = true;
463*4882a593Smuzhiyun 	d_params->fsyncs = false;
464*4882a593Smuzhiyun 	d_params->hsyncs = false;
465*4882a593Smuzhiyun 	d_params->frame_aligned = true;
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun 	ret = 0;
468*4882a593Smuzhiyun out:
469*4882a593Smuzhiyun 	return ret;
470*4882a593Smuzhiyun }
471*4882a593Smuzhiyun 
cs_etm__dump_event(struct cs_etm_auxtrace * etm,struct auxtrace_buffer * buffer)472*4882a593Smuzhiyun static void cs_etm__dump_event(struct cs_etm_auxtrace *etm,
473*4882a593Smuzhiyun 			       struct auxtrace_buffer *buffer)
474*4882a593Smuzhiyun {
475*4882a593Smuzhiyun 	int ret;
476*4882a593Smuzhiyun 	const char *color = PERF_COLOR_BLUE;
477*4882a593Smuzhiyun 	struct cs_etm_decoder_params d_params;
478*4882a593Smuzhiyun 	struct cs_etm_trace_params *t_params;
479*4882a593Smuzhiyun 	struct cs_etm_decoder *decoder;
480*4882a593Smuzhiyun 	size_t buffer_used = 0;
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 	fprintf(stdout, "\n");
483*4882a593Smuzhiyun 	color_fprintf(stdout, color,
484*4882a593Smuzhiyun 		     ". ... CoreSight ETM Trace data: size %zu bytes\n",
485*4882a593Smuzhiyun 		     buffer->size);
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 	/* Use metadata to fill in trace parameters for trace decoder */
488*4882a593Smuzhiyun 	t_params = zalloc(sizeof(*t_params) * etm->num_cpu);
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 	if (!t_params)
491*4882a593Smuzhiyun 		return;
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun 	if (cs_etm__init_trace_params(t_params, etm))
494*4882a593Smuzhiyun 		goto out_free;
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 	/* Set decoder parameters to simply print the trace packets */
497*4882a593Smuzhiyun 	if (cs_etm__init_decoder_params(&d_params, NULL,
498*4882a593Smuzhiyun 					CS_ETM_OPERATION_PRINT))
499*4882a593Smuzhiyun 		goto out_free;
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun 	decoder = cs_etm_decoder__new(etm->num_cpu, &d_params, t_params);
502*4882a593Smuzhiyun 
503*4882a593Smuzhiyun 	if (!decoder)
504*4882a593Smuzhiyun 		goto out_free;
505*4882a593Smuzhiyun 	do {
506*4882a593Smuzhiyun 		size_t consumed;
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun 		ret = cs_etm_decoder__process_data_block(
509*4882a593Smuzhiyun 				decoder, buffer->offset,
510*4882a593Smuzhiyun 				&((u8 *)buffer->data)[buffer_used],
511*4882a593Smuzhiyun 				buffer->size - buffer_used, &consumed);
512*4882a593Smuzhiyun 		if (ret)
513*4882a593Smuzhiyun 			break;
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 		buffer_used += consumed;
516*4882a593Smuzhiyun 	} while (buffer_used < buffer->size);
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun 	cs_etm_decoder__free(decoder);
519*4882a593Smuzhiyun 
520*4882a593Smuzhiyun out_free:
521*4882a593Smuzhiyun 	zfree(&t_params);
522*4882a593Smuzhiyun }
523*4882a593Smuzhiyun 
cs_etm__flush_events(struct perf_session * session,struct perf_tool * tool)524*4882a593Smuzhiyun static int cs_etm__flush_events(struct perf_session *session,
525*4882a593Smuzhiyun 				struct perf_tool *tool)
526*4882a593Smuzhiyun {
527*4882a593Smuzhiyun 	int ret;
528*4882a593Smuzhiyun 	struct cs_etm_auxtrace *etm = container_of(session->auxtrace,
529*4882a593Smuzhiyun 						   struct cs_etm_auxtrace,
530*4882a593Smuzhiyun 						   auxtrace);
531*4882a593Smuzhiyun 	if (dump_trace)
532*4882a593Smuzhiyun 		return 0;
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun 	if (!tool->ordered_events)
535*4882a593Smuzhiyun 		return -EINVAL;
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 	ret = cs_etm__update_queues(etm);
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun 	if (ret < 0)
540*4882a593Smuzhiyun 		return ret;
541*4882a593Smuzhiyun 
542*4882a593Smuzhiyun 	if (etm->timeless_decoding)
543*4882a593Smuzhiyun 		return cs_etm__process_timeless_queues(etm, -1);
544*4882a593Smuzhiyun 
545*4882a593Smuzhiyun 	return cs_etm__process_queues(etm);
546*4882a593Smuzhiyun }
547*4882a593Smuzhiyun 
cs_etm__free_traceid_queues(struct cs_etm_queue * etmq)548*4882a593Smuzhiyun static void cs_etm__free_traceid_queues(struct cs_etm_queue *etmq)
549*4882a593Smuzhiyun {
550*4882a593Smuzhiyun 	int idx;
551*4882a593Smuzhiyun 	uintptr_t priv;
552*4882a593Smuzhiyun 	struct int_node *inode, *tmp;
553*4882a593Smuzhiyun 	struct cs_etm_traceid_queue *tidq;
554*4882a593Smuzhiyun 	struct intlist *traceid_queues_list = etmq->traceid_queues_list;
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun 	intlist__for_each_entry_safe(inode, tmp, traceid_queues_list) {
557*4882a593Smuzhiyun 		priv = (uintptr_t)inode->priv;
558*4882a593Smuzhiyun 		idx = priv;
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun 		/* Free this traceid_queue from the array */
561*4882a593Smuzhiyun 		tidq = etmq->traceid_queues[idx];
562*4882a593Smuzhiyun 		thread__zput(tidq->thread);
563*4882a593Smuzhiyun 		zfree(&tidq->event_buf);
564*4882a593Smuzhiyun 		zfree(&tidq->last_branch);
565*4882a593Smuzhiyun 		zfree(&tidq->last_branch_rb);
566*4882a593Smuzhiyun 		zfree(&tidq->prev_packet);
567*4882a593Smuzhiyun 		zfree(&tidq->packet);
568*4882a593Smuzhiyun 		zfree(&tidq);
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun 		/*
571*4882a593Smuzhiyun 		 * Function intlist__remove() removes the inode from the list
572*4882a593Smuzhiyun 		 * and delete the memory associated to it.
573*4882a593Smuzhiyun 		 */
574*4882a593Smuzhiyun 		intlist__remove(traceid_queues_list, inode);
575*4882a593Smuzhiyun 	}
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun 	/* Then the RB tree itself */
578*4882a593Smuzhiyun 	intlist__delete(traceid_queues_list);
579*4882a593Smuzhiyun 	etmq->traceid_queues_list = NULL;
580*4882a593Smuzhiyun 
581*4882a593Smuzhiyun 	/* finally free the traceid_queues array */
582*4882a593Smuzhiyun 	zfree(&etmq->traceid_queues);
583*4882a593Smuzhiyun }
584*4882a593Smuzhiyun 
cs_etm__free_queue(void * priv)585*4882a593Smuzhiyun static void cs_etm__free_queue(void *priv)
586*4882a593Smuzhiyun {
587*4882a593Smuzhiyun 	struct cs_etm_queue *etmq = priv;
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun 	if (!etmq)
590*4882a593Smuzhiyun 		return;
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun 	cs_etm_decoder__free(etmq->decoder);
593*4882a593Smuzhiyun 	cs_etm__free_traceid_queues(etmq);
594*4882a593Smuzhiyun 	free(etmq);
595*4882a593Smuzhiyun }
596*4882a593Smuzhiyun 
cs_etm__free_events(struct perf_session * session)597*4882a593Smuzhiyun static void cs_etm__free_events(struct perf_session *session)
598*4882a593Smuzhiyun {
599*4882a593Smuzhiyun 	unsigned int i;
600*4882a593Smuzhiyun 	struct cs_etm_auxtrace *aux = container_of(session->auxtrace,
601*4882a593Smuzhiyun 						   struct cs_etm_auxtrace,
602*4882a593Smuzhiyun 						   auxtrace);
603*4882a593Smuzhiyun 	struct auxtrace_queues *queues = &aux->queues;
604*4882a593Smuzhiyun 
605*4882a593Smuzhiyun 	for (i = 0; i < queues->nr_queues; i++) {
606*4882a593Smuzhiyun 		cs_etm__free_queue(queues->queue_array[i].priv);
607*4882a593Smuzhiyun 		queues->queue_array[i].priv = NULL;
608*4882a593Smuzhiyun 	}
609*4882a593Smuzhiyun 
610*4882a593Smuzhiyun 	auxtrace_queues__free(queues);
611*4882a593Smuzhiyun }
612*4882a593Smuzhiyun 
cs_etm__free(struct perf_session * session)613*4882a593Smuzhiyun static void cs_etm__free(struct perf_session *session)
614*4882a593Smuzhiyun {
615*4882a593Smuzhiyun 	int i;
616*4882a593Smuzhiyun 	struct int_node *inode, *tmp;
617*4882a593Smuzhiyun 	struct cs_etm_auxtrace *aux = container_of(session->auxtrace,
618*4882a593Smuzhiyun 						   struct cs_etm_auxtrace,
619*4882a593Smuzhiyun 						   auxtrace);
620*4882a593Smuzhiyun 	cs_etm__free_events(session);
621*4882a593Smuzhiyun 	session->auxtrace = NULL;
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun 	/* First remove all traceID/metadata nodes for the RB tree */
624*4882a593Smuzhiyun 	intlist__for_each_entry_safe(inode, tmp, traceid_list)
625*4882a593Smuzhiyun 		intlist__remove(traceid_list, inode);
626*4882a593Smuzhiyun 	/* Then the RB tree itself */
627*4882a593Smuzhiyun 	intlist__delete(traceid_list);
628*4882a593Smuzhiyun 
629*4882a593Smuzhiyun 	for (i = 0; i < aux->num_cpu; i++)
630*4882a593Smuzhiyun 		zfree(&aux->metadata[i]);
631*4882a593Smuzhiyun 
632*4882a593Smuzhiyun 	thread__zput(aux->unknown_thread);
633*4882a593Smuzhiyun 	zfree(&aux->metadata);
634*4882a593Smuzhiyun 	zfree(&aux);
635*4882a593Smuzhiyun }
636*4882a593Smuzhiyun 
cs_etm__evsel_is_auxtrace(struct perf_session * session,struct evsel * evsel)637*4882a593Smuzhiyun static bool cs_etm__evsel_is_auxtrace(struct perf_session *session,
638*4882a593Smuzhiyun 				      struct evsel *evsel)
639*4882a593Smuzhiyun {
640*4882a593Smuzhiyun 	struct cs_etm_auxtrace *aux = container_of(session->auxtrace,
641*4882a593Smuzhiyun 						   struct cs_etm_auxtrace,
642*4882a593Smuzhiyun 						   auxtrace);
643*4882a593Smuzhiyun 
644*4882a593Smuzhiyun 	return evsel->core.attr.type == aux->pmu_type;
645*4882a593Smuzhiyun }
646*4882a593Smuzhiyun 
cs_etm__cpu_mode(struct cs_etm_queue * etmq,u64 address)647*4882a593Smuzhiyun static u8 cs_etm__cpu_mode(struct cs_etm_queue *etmq, u64 address)
648*4882a593Smuzhiyun {
649*4882a593Smuzhiyun 	struct machine *machine;
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun 	machine = etmq->etm->machine;
652*4882a593Smuzhiyun 
653*4882a593Smuzhiyun 	if (address >= etmq->etm->kernel_start) {
654*4882a593Smuzhiyun 		if (machine__is_host(machine))
655*4882a593Smuzhiyun 			return PERF_RECORD_MISC_KERNEL;
656*4882a593Smuzhiyun 		else
657*4882a593Smuzhiyun 			return PERF_RECORD_MISC_GUEST_KERNEL;
658*4882a593Smuzhiyun 	} else {
659*4882a593Smuzhiyun 		if (machine__is_host(machine))
660*4882a593Smuzhiyun 			return PERF_RECORD_MISC_USER;
661*4882a593Smuzhiyun 		else if (perf_guest)
662*4882a593Smuzhiyun 			return PERF_RECORD_MISC_GUEST_USER;
663*4882a593Smuzhiyun 		else
664*4882a593Smuzhiyun 			return PERF_RECORD_MISC_HYPERVISOR;
665*4882a593Smuzhiyun 	}
666*4882a593Smuzhiyun }
667*4882a593Smuzhiyun 
cs_etm__mem_access(struct cs_etm_queue * etmq,u8 trace_chan_id,u64 address,size_t size,u8 * buffer)668*4882a593Smuzhiyun static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u8 trace_chan_id,
669*4882a593Smuzhiyun 			      u64 address, size_t size, u8 *buffer)
670*4882a593Smuzhiyun {
671*4882a593Smuzhiyun 	u8  cpumode;
672*4882a593Smuzhiyun 	u64 offset;
673*4882a593Smuzhiyun 	int len;
674*4882a593Smuzhiyun 	struct thread *thread;
675*4882a593Smuzhiyun 	struct machine *machine;
676*4882a593Smuzhiyun 	struct addr_location al;
677*4882a593Smuzhiyun 	struct cs_etm_traceid_queue *tidq;
678*4882a593Smuzhiyun 
679*4882a593Smuzhiyun 	if (!etmq)
680*4882a593Smuzhiyun 		return 0;
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 	machine = etmq->etm->machine;
683*4882a593Smuzhiyun 	cpumode = cs_etm__cpu_mode(etmq, address);
684*4882a593Smuzhiyun 	tidq = cs_etm__etmq_get_traceid_queue(etmq, trace_chan_id);
685*4882a593Smuzhiyun 	if (!tidq)
686*4882a593Smuzhiyun 		return 0;
687*4882a593Smuzhiyun 
688*4882a593Smuzhiyun 	thread = tidq->thread;
689*4882a593Smuzhiyun 	if (!thread) {
690*4882a593Smuzhiyun 		if (cpumode != PERF_RECORD_MISC_KERNEL)
691*4882a593Smuzhiyun 			return 0;
692*4882a593Smuzhiyun 		thread = etmq->etm->unknown_thread;
693*4882a593Smuzhiyun 	}
694*4882a593Smuzhiyun 
695*4882a593Smuzhiyun 	if (!thread__find_map(thread, cpumode, address, &al) || !al.map->dso)
696*4882a593Smuzhiyun 		return 0;
697*4882a593Smuzhiyun 
698*4882a593Smuzhiyun 	if (al.map->dso->data.status == DSO_DATA_STATUS_ERROR &&
699*4882a593Smuzhiyun 	    dso__data_status_seen(al.map->dso, DSO_DATA_STATUS_SEEN_ITRACE))
700*4882a593Smuzhiyun 		return 0;
701*4882a593Smuzhiyun 
702*4882a593Smuzhiyun 	offset = al.map->map_ip(al.map, address);
703*4882a593Smuzhiyun 
704*4882a593Smuzhiyun 	map__load(al.map);
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun 	len = dso__data_read_offset(al.map->dso, machine, offset, buffer, size);
707*4882a593Smuzhiyun 
708*4882a593Smuzhiyun 	if (len <= 0)
709*4882a593Smuzhiyun 		return 0;
710*4882a593Smuzhiyun 
711*4882a593Smuzhiyun 	return len;
712*4882a593Smuzhiyun }
713*4882a593Smuzhiyun 
cs_etm__alloc_queue(struct cs_etm_auxtrace * etm)714*4882a593Smuzhiyun static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm)
715*4882a593Smuzhiyun {
716*4882a593Smuzhiyun 	struct cs_etm_decoder_params d_params;
717*4882a593Smuzhiyun 	struct cs_etm_trace_params  *t_params = NULL;
718*4882a593Smuzhiyun 	struct cs_etm_queue *etmq;
719*4882a593Smuzhiyun 
720*4882a593Smuzhiyun 	etmq = zalloc(sizeof(*etmq));
721*4882a593Smuzhiyun 	if (!etmq)
722*4882a593Smuzhiyun 		return NULL;
723*4882a593Smuzhiyun 
724*4882a593Smuzhiyun 	etmq->traceid_queues_list = intlist__new(NULL);
725*4882a593Smuzhiyun 	if (!etmq->traceid_queues_list)
726*4882a593Smuzhiyun 		goto out_free;
727*4882a593Smuzhiyun 
728*4882a593Smuzhiyun 	/* Use metadata to fill in trace parameters for trace decoder */
729*4882a593Smuzhiyun 	t_params = zalloc(sizeof(*t_params) * etm->num_cpu);
730*4882a593Smuzhiyun 
731*4882a593Smuzhiyun 	if (!t_params)
732*4882a593Smuzhiyun 		goto out_free;
733*4882a593Smuzhiyun 
734*4882a593Smuzhiyun 	if (cs_etm__init_trace_params(t_params, etm))
735*4882a593Smuzhiyun 		goto out_free;
736*4882a593Smuzhiyun 
737*4882a593Smuzhiyun 	/* Set decoder parameters to decode trace packets */
738*4882a593Smuzhiyun 	if (cs_etm__init_decoder_params(&d_params, etmq,
739*4882a593Smuzhiyun 					CS_ETM_OPERATION_DECODE))
740*4882a593Smuzhiyun 		goto out_free;
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun 	etmq->decoder = cs_etm_decoder__new(etm->num_cpu, &d_params, t_params);
743*4882a593Smuzhiyun 
744*4882a593Smuzhiyun 	if (!etmq->decoder)
745*4882a593Smuzhiyun 		goto out_free;
746*4882a593Smuzhiyun 
747*4882a593Smuzhiyun 	/*
748*4882a593Smuzhiyun 	 * Register a function to handle all memory accesses required by
749*4882a593Smuzhiyun 	 * the trace decoder library.
750*4882a593Smuzhiyun 	 */
751*4882a593Smuzhiyun 	if (cs_etm_decoder__add_mem_access_cb(etmq->decoder,
752*4882a593Smuzhiyun 					      0x0L, ((u64) -1L),
753*4882a593Smuzhiyun 					      cs_etm__mem_access))
754*4882a593Smuzhiyun 		goto out_free_decoder;
755*4882a593Smuzhiyun 
756*4882a593Smuzhiyun 	zfree(&t_params);
757*4882a593Smuzhiyun 	return etmq;
758*4882a593Smuzhiyun 
759*4882a593Smuzhiyun out_free_decoder:
760*4882a593Smuzhiyun 	cs_etm_decoder__free(etmq->decoder);
761*4882a593Smuzhiyun out_free:
762*4882a593Smuzhiyun 	intlist__delete(etmq->traceid_queues_list);
763*4882a593Smuzhiyun 	free(etmq);
764*4882a593Smuzhiyun 
765*4882a593Smuzhiyun 	return NULL;
766*4882a593Smuzhiyun }
767*4882a593Smuzhiyun 
cs_etm__setup_queue(struct cs_etm_auxtrace * etm,struct auxtrace_queue * queue,unsigned int queue_nr)768*4882a593Smuzhiyun static int cs_etm__setup_queue(struct cs_etm_auxtrace *etm,
769*4882a593Smuzhiyun 			       struct auxtrace_queue *queue,
770*4882a593Smuzhiyun 			       unsigned int queue_nr)
771*4882a593Smuzhiyun {
772*4882a593Smuzhiyun 	int ret = 0;
773*4882a593Smuzhiyun 	unsigned int cs_queue_nr;
774*4882a593Smuzhiyun 	u8 trace_chan_id;
775*4882a593Smuzhiyun 	u64 timestamp;
776*4882a593Smuzhiyun 	struct cs_etm_queue *etmq = queue->priv;
777*4882a593Smuzhiyun 
778*4882a593Smuzhiyun 	if (list_empty(&queue->head) || etmq)
779*4882a593Smuzhiyun 		goto out;
780*4882a593Smuzhiyun 
781*4882a593Smuzhiyun 	etmq = cs_etm__alloc_queue(etm);
782*4882a593Smuzhiyun 
783*4882a593Smuzhiyun 	if (!etmq) {
784*4882a593Smuzhiyun 		ret = -ENOMEM;
785*4882a593Smuzhiyun 		goto out;
786*4882a593Smuzhiyun 	}
787*4882a593Smuzhiyun 
788*4882a593Smuzhiyun 	queue->priv = etmq;
789*4882a593Smuzhiyun 	etmq->etm = etm;
790*4882a593Smuzhiyun 	etmq->queue_nr = queue_nr;
791*4882a593Smuzhiyun 	etmq->offset = 0;
792*4882a593Smuzhiyun 
793*4882a593Smuzhiyun 	if (etm->timeless_decoding)
794*4882a593Smuzhiyun 		goto out;
795*4882a593Smuzhiyun 
796*4882a593Smuzhiyun 	/*
797*4882a593Smuzhiyun 	 * We are under a CPU-wide trace scenario.  As such we need to know
798*4882a593Smuzhiyun 	 * when the code that generated the traces started to execute so that
799*4882a593Smuzhiyun 	 * it can be correlated with execution on other CPUs.  So we get a
800*4882a593Smuzhiyun 	 * handle on the beginning of traces and decode until we find a
801*4882a593Smuzhiyun 	 * timestamp.  The timestamp is then added to the auxtrace min heap
802*4882a593Smuzhiyun 	 * in order to know what nibble (of all the etmqs) to decode first.
803*4882a593Smuzhiyun 	 */
804*4882a593Smuzhiyun 	while (1) {
805*4882a593Smuzhiyun 		/*
806*4882a593Smuzhiyun 		 * Fetch an aux_buffer from this etmq.  Bail if no more
807*4882a593Smuzhiyun 		 * blocks or an error has been encountered.
808*4882a593Smuzhiyun 		 */
809*4882a593Smuzhiyun 		ret = cs_etm__get_data_block(etmq);
810*4882a593Smuzhiyun 		if (ret <= 0)
811*4882a593Smuzhiyun 			goto out;
812*4882a593Smuzhiyun 
813*4882a593Smuzhiyun 		/*
814*4882a593Smuzhiyun 		 * Run decoder on the trace block.  The decoder will stop when
815*4882a593Smuzhiyun 		 * encountering a timestamp, a full packet queue or the end of
816*4882a593Smuzhiyun 		 * trace for that block.
817*4882a593Smuzhiyun 		 */
818*4882a593Smuzhiyun 		ret = cs_etm__decode_data_block(etmq);
819*4882a593Smuzhiyun 		if (ret)
820*4882a593Smuzhiyun 			goto out;
821*4882a593Smuzhiyun 
822*4882a593Smuzhiyun 		/*
823*4882a593Smuzhiyun 		 * Function cs_etm_decoder__do_{hard|soft}_timestamp() does all
824*4882a593Smuzhiyun 		 * the timestamp calculation for us.
825*4882a593Smuzhiyun 		 */
826*4882a593Smuzhiyun 		timestamp = cs_etm__etmq_get_timestamp(etmq, &trace_chan_id);
827*4882a593Smuzhiyun 
828*4882a593Smuzhiyun 		/* We found a timestamp, no need to continue. */
829*4882a593Smuzhiyun 		if (timestamp)
830*4882a593Smuzhiyun 			break;
831*4882a593Smuzhiyun 
832*4882a593Smuzhiyun 		/*
833*4882a593Smuzhiyun 		 * We didn't find a timestamp so empty all the traceid packet
834*4882a593Smuzhiyun 		 * queues before looking for another timestamp packet, either
835*4882a593Smuzhiyun 		 * in the current data block or a new one.  Packets that were
836*4882a593Smuzhiyun 		 * just decoded are useless since no timestamp has been
837*4882a593Smuzhiyun 		 * associated with them.  As such simply discard them.
838*4882a593Smuzhiyun 		 */
839*4882a593Smuzhiyun 		cs_etm__clear_all_packet_queues(etmq);
840*4882a593Smuzhiyun 	}
841*4882a593Smuzhiyun 
842*4882a593Smuzhiyun 	/*
843*4882a593Smuzhiyun 	 * We have a timestamp.  Add it to the min heap to reflect when
844*4882a593Smuzhiyun 	 * instructions conveyed by the range packets of this traceID queue
845*4882a593Smuzhiyun 	 * started to execute.  Once the same has been done for all the traceID
846*4882a593Smuzhiyun 	 * queues of each etmq, redenring and decoding can start in
847*4882a593Smuzhiyun 	 * chronological order.
848*4882a593Smuzhiyun 	 *
849*4882a593Smuzhiyun 	 * Note that packets decoded above are still in the traceID's packet
850*4882a593Smuzhiyun 	 * queue and will be processed in cs_etm__process_queues().
851*4882a593Smuzhiyun 	 */
852*4882a593Smuzhiyun 	cs_queue_nr = TO_CS_QUEUE_NR(queue_nr, trace_chan_id);
853*4882a593Smuzhiyun 	ret = auxtrace_heap__add(&etm->heap, cs_queue_nr, timestamp);
854*4882a593Smuzhiyun out:
855*4882a593Smuzhiyun 	return ret;
856*4882a593Smuzhiyun }
857*4882a593Smuzhiyun 
cs_etm__setup_queues(struct cs_etm_auxtrace * etm)858*4882a593Smuzhiyun static int cs_etm__setup_queues(struct cs_etm_auxtrace *etm)
859*4882a593Smuzhiyun {
860*4882a593Smuzhiyun 	unsigned int i;
861*4882a593Smuzhiyun 	int ret;
862*4882a593Smuzhiyun 
863*4882a593Smuzhiyun 	if (!etm->kernel_start)
864*4882a593Smuzhiyun 		etm->kernel_start = machine__kernel_start(etm->machine);
865*4882a593Smuzhiyun 
866*4882a593Smuzhiyun 	for (i = 0; i < etm->queues.nr_queues; i++) {
867*4882a593Smuzhiyun 		ret = cs_etm__setup_queue(etm, &etm->queues.queue_array[i], i);
868*4882a593Smuzhiyun 		if (ret)
869*4882a593Smuzhiyun 			return ret;
870*4882a593Smuzhiyun 	}
871*4882a593Smuzhiyun 
872*4882a593Smuzhiyun 	return 0;
873*4882a593Smuzhiyun }
874*4882a593Smuzhiyun 
cs_etm__update_queues(struct cs_etm_auxtrace * etm)875*4882a593Smuzhiyun static int cs_etm__update_queues(struct cs_etm_auxtrace *etm)
876*4882a593Smuzhiyun {
877*4882a593Smuzhiyun 	if (etm->queues.new_data) {
878*4882a593Smuzhiyun 		etm->queues.new_data = false;
879*4882a593Smuzhiyun 		return cs_etm__setup_queues(etm);
880*4882a593Smuzhiyun 	}
881*4882a593Smuzhiyun 
882*4882a593Smuzhiyun 	return 0;
883*4882a593Smuzhiyun }
884*4882a593Smuzhiyun 
885*4882a593Smuzhiyun static inline
cs_etm__copy_last_branch_rb(struct cs_etm_queue * etmq,struct cs_etm_traceid_queue * tidq)886*4882a593Smuzhiyun void cs_etm__copy_last_branch_rb(struct cs_etm_queue *etmq,
887*4882a593Smuzhiyun 				 struct cs_etm_traceid_queue *tidq)
888*4882a593Smuzhiyun {
889*4882a593Smuzhiyun 	struct branch_stack *bs_src = tidq->last_branch_rb;
890*4882a593Smuzhiyun 	struct branch_stack *bs_dst = tidq->last_branch;
891*4882a593Smuzhiyun 	size_t nr = 0;
892*4882a593Smuzhiyun 
893*4882a593Smuzhiyun 	/*
894*4882a593Smuzhiyun 	 * Set the number of records before early exit: ->nr is used to
895*4882a593Smuzhiyun 	 * determine how many branches to copy from ->entries.
896*4882a593Smuzhiyun 	 */
897*4882a593Smuzhiyun 	bs_dst->nr = bs_src->nr;
898*4882a593Smuzhiyun 
899*4882a593Smuzhiyun 	/*
900*4882a593Smuzhiyun 	 * Early exit when there is nothing to copy.
901*4882a593Smuzhiyun 	 */
902*4882a593Smuzhiyun 	if (!bs_src->nr)
903*4882a593Smuzhiyun 		return;
904*4882a593Smuzhiyun 
905*4882a593Smuzhiyun 	/*
906*4882a593Smuzhiyun 	 * As bs_src->entries is a circular buffer, we need to copy from it in
907*4882a593Smuzhiyun 	 * two steps.  First, copy the branches from the most recently inserted
908*4882a593Smuzhiyun 	 * branch ->last_branch_pos until the end of bs_src->entries buffer.
909*4882a593Smuzhiyun 	 */
910*4882a593Smuzhiyun 	nr = etmq->etm->synth_opts.last_branch_sz - tidq->last_branch_pos;
911*4882a593Smuzhiyun 	memcpy(&bs_dst->entries[0],
912*4882a593Smuzhiyun 	       &bs_src->entries[tidq->last_branch_pos],
913*4882a593Smuzhiyun 	       sizeof(struct branch_entry) * nr);
914*4882a593Smuzhiyun 
915*4882a593Smuzhiyun 	/*
916*4882a593Smuzhiyun 	 * If we wrapped around at least once, the branches from the beginning
917*4882a593Smuzhiyun 	 * of the bs_src->entries buffer and until the ->last_branch_pos element
918*4882a593Smuzhiyun 	 * are older valid branches: copy them over.  The total number of
919*4882a593Smuzhiyun 	 * branches copied over will be equal to the number of branches asked by
920*4882a593Smuzhiyun 	 * the user in last_branch_sz.
921*4882a593Smuzhiyun 	 */
922*4882a593Smuzhiyun 	if (bs_src->nr >= etmq->etm->synth_opts.last_branch_sz) {
923*4882a593Smuzhiyun 		memcpy(&bs_dst->entries[nr],
924*4882a593Smuzhiyun 		       &bs_src->entries[0],
925*4882a593Smuzhiyun 		       sizeof(struct branch_entry) * tidq->last_branch_pos);
926*4882a593Smuzhiyun 	}
927*4882a593Smuzhiyun }
928*4882a593Smuzhiyun 
929*4882a593Smuzhiyun static inline
cs_etm__reset_last_branch_rb(struct cs_etm_traceid_queue * tidq)930*4882a593Smuzhiyun void cs_etm__reset_last_branch_rb(struct cs_etm_traceid_queue *tidq)
931*4882a593Smuzhiyun {
932*4882a593Smuzhiyun 	tidq->last_branch_pos = 0;
933*4882a593Smuzhiyun 	tidq->last_branch_rb->nr = 0;
934*4882a593Smuzhiyun }
935*4882a593Smuzhiyun 
cs_etm__t32_instr_size(struct cs_etm_queue * etmq,u8 trace_chan_id,u64 addr)936*4882a593Smuzhiyun static inline int cs_etm__t32_instr_size(struct cs_etm_queue *etmq,
937*4882a593Smuzhiyun 					 u8 trace_chan_id, u64 addr)
938*4882a593Smuzhiyun {
939*4882a593Smuzhiyun 	u8 instrBytes[2];
940*4882a593Smuzhiyun 
941*4882a593Smuzhiyun 	cs_etm__mem_access(etmq, trace_chan_id, addr,
942*4882a593Smuzhiyun 			   ARRAY_SIZE(instrBytes), instrBytes);
943*4882a593Smuzhiyun 	/*
944*4882a593Smuzhiyun 	 * T32 instruction size is indicated by bits[15:11] of the first
945*4882a593Smuzhiyun 	 * 16-bit word of the instruction: 0b11101, 0b11110 and 0b11111
946*4882a593Smuzhiyun 	 * denote a 32-bit instruction.
947*4882a593Smuzhiyun 	 */
948*4882a593Smuzhiyun 	return ((instrBytes[1] & 0xF8) >= 0xE8) ? 4 : 2;
949*4882a593Smuzhiyun }
950*4882a593Smuzhiyun 
cs_etm__first_executed_instr(struct cs_etm_packet * packet)951*4882a593Smuzhiyun static inline u64 cs_etm__first_executed_instr(struct cs_etm_packet *packet)
952*4882a593Smuzhiyun {
953*4882a593Smuzhiyun 	/* Returns 0 for the CS_ETM_DISCONTINUITY packet */
954*4882a593Smuzhiyun 	if (packet->sample_type == CS_ETM_DISCONTINUITY)
955*4882a593Smuzhiyun 		return 0;
956*4882a593Smuzhiyun 
957*4882a593Smuzhiyun 	return packet->start_addr;
958*4882a593Smuzhiyun }
959*4882a593Smuzhiyun 
960*4882a593Smuzhiyun static inline
cs_etm__last_executed_instr(const struct cs_etm_packet * packet)961*4882a593Smuzhiyun u64 cs_etm__last_executed_instr(const struct cs_etm_packet *packet)
962*4882a593Smuzhiyun {
963*4882a593Smuzhiyun 	/* Returns 0 for the CS_ETM_DISCONTINUITY packet */
964*4882a593Smuzhiyun 	if (packet->sample_type == CS_ETM_DISCONTINUITY)
965*4882a593Smuzhiyun 		return 0;
966*4882a593Smuzhiyun 
967*4882a593Smuzhiyun 	return packet->end_addr - packet->last_instr_size;
968*4882a593Smuzhiyun }
969*4882a593Smuzhiyun 
cs_etm__instr_addr(struct cs_etm_queue * etmq,u64 trace_chan_id,const struct cs_etm_packet * packet,u64 offset)970*4882a593Smuzhiyun static inline u64 cs_etm__instr_addr(struct cs_etm_queue *etmq,
971*4882a593Smuzhiyun 				     u64 trace_chan_id,
972*4882a593Smuzhiyun 				     const struct cs_etm_packet *packet,
973*4882a593Smuzhiyun 				     u64 offset)
974*4882a593Smuzhiyun {
975*4882a593Smuzhiyun 	if (packet->isa == CS_ETM_ISA_T32) {
976*4882a593Smuzhiyun 		u64 addr = packet->start_addr;
977*4882a593Smuzhiyun 
978*4882a593Smuzhiyun 		while (offset) {
979*4882a593Smuzhiyun 			addr += cs_etm__t32_instr_size(etmq,
980*4882a593Smuzhiyun 						       trace_chan_id, addr);
981*4882a593Smuzhiyun 			offset--;
982*4882a593Smuzhiyun 		}
983*4882a593Smuzhiyun 		return addr;
984*4882a593Smuzhiyun 	}
985*4882a593Smuzhiyun 
986*4882a593Smuzhiyun 	/* Assume a 4 byte instruction size (A32/A64) */
987*4882a593Smuzhiyun 	return packet->start_addr + offset * 4;
988*4882a593Smuzhiyun }
989*4882a593Smuzhiyun 
cs_etm__update_last_branch_rb(struct cs_etm_queue * etmq,struct cs_etm_traceid_queue * tidq)990*4882a593Smuzhiyun static void cs_etm__update_last_branch_rb(struct cs_etm_queue *etmq,
991*4882a593Smuzhiyun 					  struct cs_etm_traceid_queue *tidq)
992*4882a593Smuzhiyun {
993*4882a593Smuzhiyun 	struct branch_stack *bs = tidq->last_branch_rb;
994*4882a593Smuzhiyun 	struct branch_entry *be;
995*4882a593Smuzhiyun 
996*4882a593Smuzhiyun 	/*
997*4882a593Smuzhiyun 	 * The branches are recorded in a circular buffer in reverse
998*4882a593Smuzhiyun 	 * chronological order: we start recording from the last element of the
999*4882a593Smuzhiyun 	 * buffer down.  After writing the first element of the stack, move the
1000*4882a593Smuzhiyun 	 * insert position back to the end of the buffer.
1001*4882a593Smuzhiyun 	 */
1002*4882a593Smuzhiyun 	if (!tidq->last_branch_pos)
1003*4882a593Smuzhiyun 		tidq->last_branch_pos = etmq->etm->synth_opts.last_branch_sz;
1004*4882a593Smuzhiyun 
1005*4882a593Smuzhiyun 	tidq->last_branch_pos -= 1;
1006*4882a593Smuzhiyun 
1007*4882a593Smuzhiyun 	be       = &bs->entries[tidq->last_branch_pos];
1008*4882a593Smuzhiyun 	be->from = cs_etm__last_executed_instr(tidq->prev_packet);
1009*4882a593Smuzhiyun 	be->to	 = cs_etm__first_executed_instr(tidq->packet);
1010*4882a593Smuzhiyun 	/* No support for mispredict */
1011*4882a593Smuzhiyun 	be->flags.mispred = 0;
1012*4882a593Smuzhiyun 	be->flags.predicted = 1;
1013*4882a593Smuzhiyun 
1014*4882a593Smuzhiyun 	/*
1015*4882a593Smuzhiyun 	 * Increment bs->nr until reaching the number of last branches asked by
1016*4882a593Smuzhiyun 	 * the user on the command line.
1017*4882a593Smuzhiyun 	 */
1018*4882a593Smuzhiyun 	if (bs->nr < etmq->etm->synth_opts.last_branch_sz)
1019*4882a593Smuzhiyun 		bs->nr += 1;
1020*4882a593Smuzhiyun }
1021*4882a593Smuzhiyun 
cs_etm__inject_event(union perf_event * event,struct perf_sample * sample,u64 type)1022*4882a593Smuzhiyun static int cs_etm__inject_event(union perf_event *event,
1023*4882a593Smuzhiyun 			       struct perf_sample *sample, u64 type)
1024*4882a593Smuzhiyun {
1025*4882a593Smuzhiyun 	event->header.size = perf_event__sample_event_size(sample, type, 0);
1026*4882a593Smuzhiyun 	return perf_event__synthesize_sample(event, type, 0, sample);
1027*4882a593Smuzhiyun }
1028*4882a593Smuzhiyun 
1029*4882a593Smuzhiyun 
1030*4882a593Smuzhiyun static int
cs_etm__get_trace(struct cs_etm_queue * etmq)1031*4882a593Smuzhiyun cs_etm__get_trace(struct cs_etm_queue *etmq)
1032*4882a593Smuzhiyun {
1033*4882a593Smuzhiyun 	struct auxtrace_buffer *aux_buffer = etmq->buffer;
1034*4882a593Smuzhiyun 	struct auxtrace_buffer *old_buffer = aux_buffer;
1035*4882a593Smuzhiyun 	struct auxtrace_queue *queue;
1036*4882a593Smuzhiyun 
1037*4882a593Smuzhiyun 	queue = &etmq->etm->queues.queue_array[etmq->queue_nr];
1038*4882a593Smuzhiyun 
1039*4882a593Smuzhiyun 	aux_buffer = auxtrace_buffer__next(queue, aux_buffer);
1040*4882a593Smuzhiyun 
1041*4882a593Smuzhiyun 	/* If no more data, drop the previous auxtrace_buffer and return */
1042*4882a593Smuzhiyun 	if (!aux_buffer) {
1043*4882a593Smuzhiyun 		if (old_buffer)
1044*4882a593Smuzhiyun 			auxtrace_buffer__drop_data(old_buffer);
1045*4882a593Smuzhiyun 		etmq->buf_len = 0;
1046*4882a593Smuzhiyun 		return 0;
1047*4882a593Smuzhiyun 	}
1048*4882a593Smuzhiyun 
1049*4882a593Smuzhiyun 	etmq->buffer = aux_buffer;
1050*4882a593Smuzhiyun 
1051*4882a593Smuzhiyun 	/* If the aux_buffer doesn't have data associated, try to load it */
1052*4882a593Smuzhiyun 	if (!aux_buffer->data) {
1053*4882a593Smuzhiyun 		/* get the file desc associated with the perf data file */
1054*4882a593Smuzhiyun 		int fd = perf_data__fd(etmq->etm->session->data);
1055*4882a593Smuzhiyun 
1056*4882a593Smuzhiyun 		aux_buffer->data = auxtrace_buffer__get_data(aux_buffer, fd);
1057*4882a593Smuzhiyun 		if (!aux_buffer->data)
1058*4882a593Smuzhiyun 			return -ENOMEM;
1059*4882a593Smuzhiyun 	}
1060*4882a593Smuzhiyun 
1061*4882a593Smuzhiyun 	/* If valid, drop the previous buffer */
1062*4882a593Smuzhiyun 	if (old_buffer)
1063*4882a593Smuzhiyun 		auxtrace_buffer__drop_data(old_buffer);
1064*4882a593Smuzhiyun 
1065*4882a593Smuzhiyun 	etmq->buf_used = 0;
1066*4882a593Smuzhiyun 	etmq->buf_len = aux_buffer->size;
1067*4882a593Smuzhiyun 	etmq->buf = aux_buffer->data;
1068*4882a593Smuzhiyun 
1069*4882a593Smuzhiyun 	return etmq->buf_len;
1070*4882a593Smuzhiyun }
1071*4882a593Smuzhiyun 
cs_etm__set_pid_tid_cpu(struct cs_etm_auxtrace * etm,struct cs_etm_traceid_queue * tidq)1072*4882a593Smuzhiyun static void cs_etm__set_pid_tid_cpu(struct cs_etm_auxtrace *etm,
1073*4882a593Smuzhiyun 				    struct cs_etm_traceid_queue *tidq)
1074*4882a593Smuzhiyun {
1075*4882a593Smuzhiyun 	if ((!tidq->thread) && (tidq->tid != -1))
1076*4882a593Smuzhiyun 		tidq->thread = machine__find_thread(etm->machine, -1,
1077*4882a593Smuzhiyun 						    tidq->tid);
1078*4882a593Smuzhiyun 
1079*4882a593Smuzhiyun 	if (tidq->thread)
1080*4882a593Smuzhiyun 		tidq->pid = tidq->thread->pid_;
1081*4882a593Smuzhiyun }
1082*4882a593Smuzhiyun 
cs_etm__etmq_set_tid(struct cs_etm_queue * etmq,pid_t tid,u8 trace_chan_id)1083*4882a593Smuzhiyun int cs_etm__etmq_set_tid(struct cs_etm_queue *etmq,
1084*4882a593Smuzhiyun 			 pid_t tid, u8 trace_chan_id)
1085*4882a593Smuzhiyun {
1086*4882a593Smuzhiyun 	int cpu, err = -EINVAL;
1087*4882a593Smuzhiyun 	struct cs_etm_auxtrace *etm = etmq->etm;
1088*4882a593Smuzhiyun 	struct cs_etm_traceid_queue *tidq;
1089*4882a593Smuzhiyun 
1090*4882a593Smuzhiyun 	tidq = cs_etm__etmq_get_traceid_queue(etmq, trace_chan_id);
1091*4882a593Smuzhiyun 	if (!tidq)
1092*4882a593Smuzhiyun 		return err;
1093*4882a593Smuzhiyun 
1094*4882a593Smuzhiyun 	if (cs_etm__get_cpu(trace_chan_id, &cpu) < 0)
1095*4882a593Smuzhiyun 		return err;
1096*4882a593Smuzhiyun 
1097*4882a593Smuzhiyun 	err = machine__set_current_tid(etm->machine, cpu, tid, tid);
1098*4882a593Smuzhiyun 	if (err)
1099*4882a593Smuzhiyun 		return err;
1100*4882a593Smuzhiyun 
1101*4882a593Smuzhiyun 	tidq->tid = tid;
1102*4882a593Smuzhiyun 	thread__zput(tidq->thread);
1103*4882a593Smuzhiyun 
1104*4882a593Smuzhiyun 	cs_etm__set_pid_tid_cpu(etm, tidq);
1105*4882a593Smuzhiyun 	return 0;
1106*4882a593Smuzhiyun }
1107*4882a593Smuzhiyun 
cs_etm__etmq_is_timeless(struct cs_etm_queue * etmq)1108*4882a593Smuzhiyun bool cs_etm__etmq_is_timeless(struct cs_etm_queue *etmq)
1109*4882a593Smuzhiyun {
1110*4882a593Smuzhiyun 	return !!etmq->etm->timeless_decoding;
1111*4882a593Smuzhiyun }
1112*4882a593Smuzhiyun 
cs_etm__copy_insn(struct cs_etm_queue * etmq,u64 trace_chan_id,const struct cs_etm_packet * packet,struct perf_sample * sample)1113*4882a593Smuzhiyun static void cs_etm__copy_insn(struct cs_etm_queue *etmq,
1114*4882a593Smuzhiyun 			      u64 trace_chan_id,
1115*4882a593Smuzhiyun 			      const struct cs_etm_packet *packet,
1116*4882a593Smuzhiyun 			      struct perf_sample *sample)
1117*4882a593Smuzhiyun {
1118*4882a593Smuzhiyun 	/*
1119*4882a593Smuzhiyun 	 * It's pointless to read instructions for the CS_ETM_DISCONTINUITY
1120*4882a593Smuzhiyun 	 * packet, so directly bail out with 'insn_len' = 0.
1121*4882a593Smuzhiyun 	 */
1122*4882a593Smuzhiyun 	if (packet->sample_type == CS_ETM_DISCONTINUITY) {
1123*4882a593Smuzhiyun 		sample->insn_len = 0;
1124*4882a593Smuzhiyun 		return;
1125*4882a593Smuzhiyun 	}
1126*4882a593Smuzhiyun 
1127*4882a593Smuzhiyun 	/*
1128*4882a593Smuzhiyun 	 * T32 instruction size might be 32-bit or 16-bit, decide by calling
1129*4882a593Smuzhiyun 	 * cs_etm__t32_instr_size().
1130*4882a593Smuzhiyun 	 */
1131*4882a593Smuzhiyun 	if (packet->isa == CS_ETM_ISA_T32)
1132*4882a593Smuzhiyun 		sample->insn_len = cs_etm__t32_instr_size(etmq, trace_chan_id,
1133*4882a593Smuzhiyun 							  sample->ip);
1134*4882a593Smuzhiyun 	/* Otherwise, A64 and A32 instruction size are always 32-bit. */
1135*4882a593Smuzhiyun 	else
1136*4882a593Smuzhiyun 		sample->insn_len = 4;
1137*4882a593Smuzhiyun 
1138*4882a593Smuzhiyun 	cs_etm__mem_access(etmq, trace_chan_id, sample->ip,
1139*4882a593Smuzhiyun 			   sample->insn_len, (void *)sample->insn);
1140*4882a593Smuzhiyun }
1141*4882a593Smuzhiyun 
cs_etm__synth_instruction_sample(struct cs_etm_queue * etmq,struct cs_etm_traceid_queue * tidq,u64 addr,u64 period)1142*4882a593Smuzhiyun static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq,
1143*4882a593Smuzhiyun 					    struct cs_etm_traceid_queue *tidq,
1144*4882a593Smuzhiyun 					    u64 addr, u64 period)
1145*4882a593Smuzhiyun {
1146*4882a593Smuzhiyun 	int ret = 0;
1147*4882a593Smuzhiyun 	struct cs_etm_auxtrace *etm = etmq->etm;
1148*4882a593Smuzhiyun 	union perf_event *event = tidq->event_buf;
1149*4882a593Smuzhiyun 	struct perf_sample sample = {.ip = 0,};
1150*4882a593Smuzhiyun 
1151*4882a593Smuzhiyun 	event->sample.header.type = PERF_RECORD_SAMPLE;
1152*4882a593Smuzhiyun 	event->sample.header.misc = cs_etm__cpu_mode(etmq, addr);
1153*4882a593Smuzhiyun 	event->sample.header.size = sizeof(struct perf_event_header);
1154*4882a593Smuzhiyun 
1155*4882a593Smuzhiyun 	sample.ip = addr;
1156*4882a593Smuzhiyun 	sample.pid = tidq->pid;
1157*4882a593Smuzhiyun 	sample.tid = tidq->tid;
1158*4882a593Smuzhiyun 	sample.id = etmq->etm->instructions_id;
1159*4882a593Smuzhiyun 	sample.stream_id = etmq->etm->instructions_id;
1160*4882a593Smuzhiyun 	sample.period = period;
1161*4882a593Smuzhiyun 	sample.cpu = tidq->packet->cpu;
1162*4882a593Smuzhiyun 	sample.flags = tidq->prev_packet->flags;
1163*4882a593Smuzhiyun 	sample.cpumode = event->sample.header.misc;
1164*4882a593Smuzhiyun 
1165*4882a593Smuzhiyun 	cs_etm__copy_insn(etmq, tidq->trace_chan_id, tidq->packet, &sample);
1166*4882a593Smuzhiyun 
1167*4882a593Smuzhiyun 	if (etm->synth_opts.last_branch)
1168*4882a593Smuzhiyun 		sample.branch_stack = tidq->last_branch;
1169*4882a593Smuzhiyun 
1170*4882a593Smuzhiyun 	if (etm->synth_opts.inject) {
1171*4882a593Smuzhiyun 		ret = cs_etm__inject_event(event, &sample,
1172*4882a593Smuzhiyun 					   etm->instructions_sample_type);
1173*4882a593Smuzhiyun 		if (ret)
1174*4882a593Smuzhiyun 			return ret;
1175*4882a593Smuzhiyun 	}
1176*4882a593Smuzhiyun 
1177*4882a593Smuzhiyun 	ret = perf_session__deliver_synth_event(etm->session, event, &sample);
1178*4882a593Smuzhiyun 
1179*4882a593Smuzhiyun 	if (ret)
1180*4882a593Smuzhiyun 		pr_err(
1181*4882a593Smuzhiyun 			"CS ETM Trace: failed to deliver instruction event, error %d\n",
1182*4882a593Smuzhiyun 			ret);
1183*4882a593Smuzhiyun 
1184*4882a593Smuzhiyun 	return ret;
1185*4882a593Smuzhiyun }
1186*4882a593Smuzhiyun 
1187*4882a593Smuzhiyun /*
1188*4882a593Smuzhiyun  * The cs etm packet encodes an instruction range between a branch target
1189*4882a593Smuzhiyun  * and the next taken branch. Generate sample accordingly.
1190*4882a593Smuzhiyun  */
cs_etm__synth_branch_sample(struct cs_etm_queue * etmq,struct cs_etm_traceid_queue * tidq)1191*4882a593Smuzhiyun static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq,
1192*4882a593Smuzhiyun 				       struct cs_etm_traceid_queue *tidq)
1193*4882a593Smuzhiyun {
1194*4882a593Smuzhiyun 	int ret = 0;
1195*4882a593Smuzhiyun 	struct cs_etm_auxtrace *etm = etmq->etm;
1196*4882a593Smuzhiyun 	struct perf_sample sample = {.ip = 0,};
1197*4882a593Smuzhiyun 	union perf_event *event = tidq->event_buf;
1198*4882a593Smuzhiyun 	struct dummy_branch_stack {
1199*4882a593Smuzhiyun 		u64			nr;
1200*4882a593Smuzhiyun 		u64			hw_idx;
1201*4882a593Smuzhiyun 		struct branch_entry	entries;
1202*4882a593Smuzhiyun 	} dummy_bs;
1203*4882a593Smuzhiyun 	u64 ip;
1204*4882a593Smuzhiyun 
1205*4882a593Smuzhiyun 	ip = cs_etm__last_executed_instr(tidq->prev_packet);
1206*4882a593Smuzhiyun 
1207*4882a593Smuzhiyun 	event->sample.header.type = PERF_RECORD_SAMPLE;
1208*4882a593Smuzhiyun 	event->sample.header.misc = cs_etm__cpu_mode(etmq, ip);
1209*4882a593Smuzhiyun 	event->sample.header.size = sizeof(struct perf_event_header);
1210*4882a593Smuzhiyun 
1211*4882a593Smuzhiyun 	sample.ip = ip;
1212*4882a593Smuzhiyun 	sample.pid = tidq->pid;
1213*4882a593Smuzhiyun 	sample.tid = tidq->tid;
1214*4882a593Smuzhiyun 	sample.addr = cs_etm__first_executed_instr(tidq->packet);
1215*4882a593Smuzhiyun 	sample.id = etmq->etm->branches_id;
1216*4882a593Smuzhiyun 	sample.stream_id = etmq->etm->branches_id;
1217*4882a593Smuzhiyun 	sample.period = 1;
1218*4882a593Smuzhiyun 	sample.cpu = tidq->packet->cpu;
1219*4882a593Smuzhiyun 	sample.flags = tidq->prev_packet->flags;
1220*4882a593Smuzhiyun 	sample.cpumode = event->sample.header.misc;
1221*4882a593Smuzhiyun 
1222*4882a593Smuzhiyun 	cs_etm__copy_insn(etmq, tidq->trace_chan_id, tidq->prev_packet,
1223*4882a593Smuzhiyun 			  &sample);
1224*4882a593Smuzhiyun 
1225*4882a593Smuzhiyun 	/*
1226*4882a593Smuzhiyun 	 * perf report cannot handle events without a branch stack
1227*4882a593Smuzhiyun 	 */
1228*4882a593Smuzhiyun 	if (etm->synth_opts.last_branch) {
1229*4882a593Smuzhiyun 		dummy_bs = (struct dummy_branch_stack){
1230*4882a593Smuzhiyun 			.nr = 1,
1231*4882a593Smuzhiyun 			.hw_idx = -1ULL,
1232*4882a593Smuzhiyun 			.entries = {
1233*4882a593Smuzhiyun 				.from = sample.ip,
1234*4882a593Smuzhiyun 				.to = sample.addr,
1235*4882a593Smuzhiyun 			},
1236*4882a593Smuzhiyun 		};
1237*4882a593Smuzhiyun 		sample.branch_stack = (struct branch_stack *)&dummy_bs;
1238*4882a593Smuzhiyun 	}
1239*4882a593Smuzhiyun 
1240*4882a593Smuzhiyun 	if (etm->synth_opts.inject) {
1241*4882a593Smuzhiyun 		ret = cs_etm__inject_event(event, &sample,
1242*4882a593Smuzhiyun 					   etm->branches_sample_type);
1243*4882a593Smuzhiyun 		if (ret)
1244*4882a593Smuzhiyun 			return ret;
1245*4882a593Smuzhiyun 	}
1246*4882a593Smuzhiyun 
1247*4882a593Smuzhiyun 	ret = perf_session__deliver_synth_event(etm->session, event, &sample);
1248*4882a593Smuzhiyun 
1249*4882a593Smuzhiyun 	if (ret)
1250*4882a593Smuzhiyun 		pr_err(
1251*4882a593Smuzhiyun 		"CS ETM Trace: failed to deliver instruction event, error %d\n",
1252*4882a593Smuzhiyun 		ret);
1253*4882a593Smuzhiyun 
1254*4882a593Smuzhiyun 	return ret;
1255*4882a593Smuzhiyun }
1256*4882a593Smuzhiyun 
1257*4882a593Smuzhiyun struct cs_etm_synth {
1258*4882a593Smuzhiyun 	struct perf_tool dummy_tool;
1259*4882a593Smuzhiyun 	struct perf_session *session;
1260*4882a593Smuzhiyun };
1261*4882a593Smuzhiyun 
cs_etm__event_synth(struct perf_tool * tool,union perf_event * event,struct perf_sample * sample __maybe_unused,struct machine * machine __maybe_unused)1262*4882a593Smuzhiyun static int cs_etm__event_synth(struct perf_tool *tool,
1263*4882a593Smuzhiyun 			       union perf_event *event,
1264*4882a593Smuzhiyun 			       struct perf_sample *sample __maybe_unused,
1265*4882a593Smuzhiyun 			       struct machine *machine __maybe_unused)
1266*4882a593Smuzhiyun {
1267*4882a593Smuzhiyun 	struct cs_etm_synth *cs_etm_synth =
1268*4882a593Smuzhiyun 		      container_of(tool, struct cs_etm_synth, dummy_tool);
1269*4882a593Smuzhiyun 
1270*4882a593Smuzhiyun 	return perf_session__deliver_synth_event(cs_etm_synth->session,
1271*4882a593Smuzhiyun 						 event, NULL);
1272*4882a593Smuzhiyun }
1273*4882a593Smuzhiyun 
cs_etm__synth_event(struct perf_session * session,struct perf_event_attr * attr,u64 id)1274*4882a593Smuzhiyun static int cs_etm__synth_event(struct perf_session *session,
1275*4882a593Smuzhiyun 			       struct perf_event_attr *attr, u64 id)
1276*4882a593Smuzhiyun {
1277*4882a593Smuzhiyun 	struct cs_etm_synth cs_etm_synth;
1278*4882a593Smuzhiyun 
1279*4882a593Smuzhiyun 	memset(&cs_etm_synth, 0, sizeof(struct cs_etm_synth));
1280*4882a593Smuzhiyun 	cs_etm_synth.session = session;
1281*4882a593Smuzhiyun 
1282*4882a593Smuzhiyun 	return perf_event__synthesize_attr(&cs_etm_synth.dummy_tool, attr, 1,
1283*4882a593Smuzhiyun 					   &id, cs_etm__event_synth);
1284*4882a593Smuzhiyun }
1285*4882a593Smuzhiyun 
cs_etm__synth_events(struct cs_etm_auxtrace * etm,struct perf_session * session)1286*4882a593Smuzhiyun static int cs_etm__synth_events(struct cs_etm_auxtrace *etm,
1287*4882a593Smuzhiyun 				struct perf_session *session)
1288*4882a593Smuzhiyun {
1289*4882a593Smuzhiyun 	struct evlist *evlist = session->evlist;
1290*4882a593Smuzhiyun 	struct evsel *evsel;
1291*4882a593Smuzhiyun 	struct perf_event_attr attr;
1292*4882a593Smuzhiyun 	bool found = false;
1293*4882a593Smuzhiyun 	u64 id;
1294*4882a593Smuzhiyun 	int err;
1295*4882a593Smuzhiyun 
1296*4882a593Smuzhiyun 	evlist__for_each_entry(evlist, evsel) {
1297*4882a593Smuzhiyun 		if (evsel->core.attr.type == etm->pmu_type) {
1298*4882a593Smuzhiyun 			found = true;
1299*4882a593Smuzhiyun 			break;
1300*4882a593Smuzhiyun 		}
1301*4882a593Smuzhiyun 	}
1302*4882a593Smuzhiyun 
1303*4882a593Smuzhiyun 	if (!found) {
1304*4882a593Smuzhiyun 		pr_debug("No selected events with CoreSight Trace data\n");
1305*4882a593Smuzhiyun 		return 0;
1306*4882a593Smuzhiyun 	}
1307*4882a593Smuzhiyun 
1308*4882a593Smuzhiyun 	memset(&attr, 0, sizeof(struct perf_event_attr));
1309*4882a593Smuzhiyun 	attr.size = sizeof(struct perf_event_attr);
1310*4882a593Smuzhiyun 	attr.type = PERF_TYPE_HARDWARE;
1311*4882a593Smuzhiyun 	attr.sample_type = evsel->core.attr.sample_type & PERF_SAMPLE_MASK;
1312*4882a593Smuzhiyun 	attr.sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID |
1313*4882a593Smuzhiyun 			    PERF_SAMPLE_PERIOD;
1314*4882a593Smuzhiyun 	if (etm->timeless_decoding)
1315*4882a593Smuzhiyun 		attr.sample_type &= ~(u64)PERF_SAMPLE_TIME;
1316*4882a593Smuzhiyun 	else
1317*4882a593Smuzhiyun 		attr.sample_type |= PERF_SAMPLE_TIME;
1318*4882a593Smuzhiyun 
1319*4882a593Smuzhiyun 	attr.exclude_user = evsel->core.attr.exclude_user;
1320*4882a593Smuzhiyun 	attr.exclude_kernel = evsel->core.attr.exclude_kernel;
1321*4882a593Smuzhiyun 	attr.exclude_hv = evsel->core.attr.exclude_hv;
1322*4882a593Smuzhiyun 	attr.exclude_host = evsel->core.attr.exclude_host;
1323*4882a593Smuzhiyun 	attr.exclude_guest = evsel->core.attr.exclude_guest;
1324*4882a593Smuzhiyun 	attr.sample_id_all = evsel->core.attr.sample_id_all;
1325*4882a593Smuzhiyun 	attr.read_format = evsel->core.attr.read_format;
1326*4882a593Smuzhiyun 
1327*4882a593Smuzhiyun 	/* create new id val to be a fixed offset from evsel id */
1328*4882a593Smuzhiyun 	id = evsel->core.id[0] + 1000000000;
1329*4882a593Smuzhiyun 
1330*4882a593Smuzhiyun 	if (!id)
1331*4882a593Smuzhiyun 		id = 1;
1332*4882a593Smuzhiyun 
1333*4882a593Smuzhiyun 	if (etm->synth_opts.branches) {
1334*4882a593Smuzhiyun 		attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
1335*4882a593Smuzhiyun 		attr.sample_period = 1;
1336*4882a593Smuzhiyun 		attr.sample_type |= PERF_SAMPLE_ADDR;
1337*4882a593Smuzhiyun 		err = cs_etm__synth_event(session, &attr, id);
1338*4882a593Smuzhiyun 		if (err)
1339*4882a593Smuzhiyun 			return err;
1340*4882a593Smuzhiyun 		etm->sample_branches = true;
1341*4882a593Smuzhiyun 		etm->branches_sample_type = attr.sample_type;
1342*4882a593Smuzhiyun 		etm->branches_id = id;
1343*4882a593Smuzhiyun 		id += 1;
1344*4882a593Smuzhiyun 		attr.sample_type &= ~(u64)PERF_SAMPLE_ADDR;
1345*4882a593Smuzhiyun 	}
1346*4882a593Smuzhiyun 
1347*4882a593Smuzhiyun 	if (etm->synth_opts.last_branch) {
1348*4882a593Smuzhiyun 		attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
1349*4882a593Smuzhiyun 		/*
1350*4882a593Smuzhiyun 		 * We don't use the hardware index, but the sample generation
1351*4882a593Smuzhiyun 		 * code uses the new format branch_stack with this field,
1352*4882a593Smuzhiyun 		 * so the event attributes must indicate that it's present.
1353*4882a593Smuzhiyun 		 */
1354*4882a593Smuzhiyun 		attr.branch_sample_type |= PERF_SAMPLE_BRANCH_HW_INDEX;
1355*4882a593Smuzhiyun 	}
1356*4882a593Smuzhiyun 
1357*4882a593Smuzhiyun 	if (etm->synth_opts.instructions) {
1358*4882a593Smuzhiyun 		attr.config = PERF_COUNT_HW_INSTRUCTIONS;
1359*4882a593Smuzhiyun 		attr.sample_period = etm->synth_opts.period;
1360*4882a593Smuzhiyun 		etm->instructions_sample_period = attr.sample_period;
1361*4882a593Smuzhiyun 		err = cs_etm__synth_event(session, &attr, id);
1362*4882a593Smuzhiyun 		if (err)
1363*4882a593Smuzhiyun 			return err;
1364*4882a593Smuzhiyun 		etm->sample_instructions = true;
1365*4882a593Smuzhiyun 		etm->instructions_sample_type = attr.sample_type;
1366*4882a593Smuzhiyun 		etm->instructions_id = id;
1367*4882a593Smuzhiyun 		id += 1;
1368*4882a593Smuzhiyun 	}
1369*4882a593Smuzhiyun 
1370*4882a593Smuzhiyun 	return 0;
1371*4882a593Smuzhiyun }
1372*4882a593Smuzhiyun 
cs_etm__sample(struct cs_etm_queue * etmq,struct cs_etm_traceid_queue * tidq)1373*4882a593Smuzhiyun static int cs_etm__sample(struct cs_etm_queue *etmq,
1374*4882a593Smuzhiyun 			  struct cs_etm_traceid_queue *tidq)
1375*4882a593Smuzhiyun {
1376*4882a593Smuzhiyun 	struct cs_etm_auxtrace *etm = etmq->etm;
1377*4882a593Smuzhiyun 	int ret;
1378*4882a593Smuzhiyun 	u8 trace_chan_id = tidq->trace_chan_id;
1379*4882a593Smuzhiyun 	u64 instrs_prev;
1380*4882a593Smuzhiyun 
1381*4882a593Smuzhiyun 	/* Get instructions remainder from previous packet */
1382*4882a593Smuzhiyun 	instrs_prev = tidq->period_instructions;
1383*4882a593Smuzhiyun 
1384*4882a593Smuzhiyun 	tidq->period_instructions += tidq->packet->instr_count;
1385*4882a593Smuzhiyun 
1386*4882a593Smuzhiyun 	/*
1387*4882a593Smuzhiyun 	 * Record a branch when the last instruction in
1388*4882a593Smuzhiyun 	 * PREV_PACKET is a branch.
1389*4882a593Smuzhiyun 	 */
1390*4882a593Smuzhiyun 	if (etm->synth_opts.last_branch &&
1391*4882a593Smuzhiyun 	    tidq->prev_packet->sample_type == CS_ETM_RANGE &&
1392*4882a593Smuzhiyun 	    tidq->prev_packet->last_instr_taken_branch)
1393*4882a593Smuzhiyun 		cs_etm__update_last_branch_rb(etmq, tidq);
1394*4882a593Smuzhiyun 
1395*4882a593Smuzhiyun 	if (etm->sample_instructions &&
1396*4882a593Smuzhiyun 	    tidq->period_instructions >= etm->instructions_sample_period) {
1397*4882a593Smuzhiyun 		/*
1398*4882a593Smuzhiyun 		 * Emit instruction sample periodically
1399*4882a593Smuzhiyun 		 * TODO: allow period to be defined in cycles and clock time
1400*4882a593Smuzhiyun 		 */
1401*4882a593Smuzhiyun 
1402*4882a593Smuzhiyun 		/*
1403*4882a593Smuzhiyun 		 * Below diagram demonstrates the instruction samples
1404*4882a593Smuzhiyun 		 * generation flows:
1405*4882a593Smuzhiyun 		 *
1406*4882a593Smuzhiyun 		 *    Instrs     Instrs       Instrs       Instrs
1407*4882a593Smuzhiyun 		 *   Sample(n)  Sample(n+1)  Sample(n+2)  Sample(n+3)
1408*4882a593Smuzhiyun 		 *    |            |            |            |
1409*4882a593Smuzhiyun 		 *    V            V            V            V
1410*4882a593Smuzhiyun 		 *   --------------------------------------------------
1411*4882a593Smuzhiyun 		 *            ^                                  ^
1412*4882a593Smuzhiyun 		 *            |                                  |
1413*4882a593Smuzhiyun 		 *         Period                             Period
1414*4882a593Smuzhiyun 		 *    instructions(Pi)                   instructions(Pi')
1415*4882a593Smuzhiyun 		 *
1416*4882a593Smuzhiyun 		 *            |                                  |
1417*4882a593Smuzhiyun 		 *            \---------------- -----------------/
1418*4882a593Smuzhiyun 		 *                             V
1419*4882a593Smuzhiyun 		 *                 tidq->packet->instr_count
1420*4882a593Smuzhiyun 		 *
1421*4882a593Smuzhiyun 		 * Instrs Sample(n...) are the synthesised samples occurring
1422*4882a593Smuzhiyun 		 * every etm->instructions_sample_period instructions - as
1423*4882a593Smuzhiyun 		 * defined on the perf command line.  Sample(n) is being the
1424*4882a593Smuzhiyun 		 * last sample before the current etm packet, n+1 to n+3
1425*4882a593Smuzhiyun 		 * samples are generated from the current etm packet.
1426*4882a593Smuzhiyun 		 *
1427*4882a593Smuzhiyun 		 * tidq->packet->instr_count represents the number of
1428*4882a593Smuzhiyun 		 * instructions in the current etm packet.
1429*4882a593Smuzhiyun 		 *
1430*4882a593Smuzhiyun 		 * Period instructions (Pi) contains the the number of
1431*4882a593Smuzhiyun 		 * instructions executed after the sample point(n) from the
1432*4882a593Smuzhiyun 		 * previous etm packet.  This will always be less than
1433*4882a593Smuzhiyun 		 * etm->instructions_sample_period.
1434*4882a593Smuzhiyun 		 *
1435*4882a593Smuzhiyun 		 * When generate new samples, it combines with two parts
1436*4882a593Smuzhiyun 		 * instructions, one is the tail of the old packet and another
1437*4882a593Smuzhiyun 		 * is the head of the new coming packet, to generate
1438*4882a593Smuzhiyun 		 * sample(n+1); sample(n+2) and sample(n+3) consume the
1439*4882a593Smuzhiyun 		 * instructions with sample period.  After sample(n+3), the rest
1440*4882a593Smuzhiyun 		 * instructions will be used by later packet and it is assigned
1441*4882a593Smuzhiyun 		 * to tidq->period_instructions for next round calculation.
1442*4882a593Smuzhiyun 		 */
1443*4882a593Smuzhiyun 
1444*4882a593Smuzhiyun 		/*
1445*4882a593Smuzhiyun 		 * Get the initial offset into the current packet instructions;
1446*4882a593Smuzhiyun 		 * entry conditions ensure that instrs_prev is less than
1447*4882a593Smuzhiyun 		 * etm->instructions_sample_period.
1448*4882a593Smuzhiyun 		 */
1449*4882a593Smuzhiyun 		u64 offset = etm->instructions_sample_period - instrs_prev;
1450*4882a593Smuzhiyun 		u64 addr;
1451*4882a593Smuzhiyun 
1452*4882a593Smuzhiyun 		/* Prepare last branches for instruction sample */
1453*4882a593Smuzhiyun 		if (etm->synth_opts.last_branch)
1454*4882a593Smuzhiyun 			cs_etm__copy_last_branch_rb(etmq, tidq);
1455*4882a593Smuzhiyun 
1456*4882a593Smuzhiyun 		while (tidq->period_instructions >=
1457*4882a593Smuzhiyun 				etm->instructions_sample_period) {
1458*4882a593Smuzhiyun 			/*
1459*4882a593Smuzhiyun 			 * Calculate the address of the sampled instruction (-1
1460*4882a593Smuzhiyun 			 * as sample is reported as though instruction has just
1461*4882a593Smuzhiyun 			 * been executed, but PC has not advanced to next
1462*4882a593Smuzhiyun 			 * instruction)
1463*4882a593Smuzhiyun 			 */
1464*4882a593Smuzhiyun 			addr = cs_etm__instr_addr(etmq, trace_chan_id,
1465*4882a593Smuzhiyun 						  tidq->packet, offset - 1);
1466*4882a593Smuzhiyun 			ret = cs_etm__synth_instruction_sample(
1467*4882a593Smuzhiyun 				etmq, tidq, addr,
1468*4882a593Smuzhiyun 				etm->instructions_sample_period);
1469*4882a593Smuzhiyun 			if (ret)
1470*4882a593Smuzhiyun 				return ret;
1471*4882a593Smuzhiyun 
1472*4882a593Smuzhiyun 			offset += etm->instructions_sample_period;
1473*4882a593Smuzhiyun 			tidq->period_instructions -=
1474*4882a593Smuzhiyun 				etm->instructions_sample_period;
1475*4882a593Smuzhiyun 		}
1476*4882a593Smuzhiyun 	}
1477*4882a593Smuzhiyun 
1478*4882a593Smuzhiyun 	if (etm->sample_branches) {
1479*4882a593Smuzhiyun 		bool generate_sample = false;
1480*4882a593Smuzhiyun 
1481*4882a593Smuzhiyun 		/* Generate sample for tracing on packet */
1482*4882a593Smuzhiyun 		if (tidq->prev_packet->sample_type == CS_ETM_DISCONTINUITY)
1483*4882a593Smuzhiyun 			generate_sample = true;
1484*4882a593Smuzhiyun 
1485*4882a593Smuzhiyun 		/* Generate sample for branch taken packet */
1486*4882a593Smuzhiyun 		if (tidq->prev_packet->sample_type == CS_ETM_RANGE &&
1487*4882a593Smuzhiyun 		    tidq->prev_packet->last_instr_taken_branch)
1488*4882a593Smuzhiyun 			generate_sample = true;
1489*4882a593Smuzhiyun 
1490*4882a593Smuzhiyun 		if (generate_sample) {
1491*4882a593Smuzhiyun 			ret = cs_etm__synth_branch_sample(etmq, tidq);
1492*4882a593Smuzhiyun 			if (ret)
1493*4882a593Smuzhiyun 				return ret;
1494*4882a593Smuzhiyun 		}
1495*4882a593Smuzhiyun 	}
1496*4882a593Smuzhiyun 
1497*4882a593Smuzhiyun 	cs_etm__packet_swap(etm, tidq);
1498*4882a593Smuzhiyun 
1499*4882a593Smuzhiyun 	return 0;
1500*4882a593Smuzhiyun }
1501*4882a593Smuzhiyun 
cs_etm__exception(struct cs_etm_traceid_queue * tidq)1502*4882a593Smuzhiyun static int cs_etm__exception(struct cs_etm_traceid_queue *tidq)
1503*4882a593Smuzhiyun {
1504*4882a593Smuzhiyun 	/*
1505*4882a593Smuzhiyun 	 * When the exception packet is inserted, whether the last instruction
1506*4882a593Smuzhiyun 	 * in previous range packet is taken branch or not, we need to force
1507*4882a593Smuzhiyun 	 * to set 'prev_packet->last_instr_taken_branch' to true.  This ensures
1508*4882a593Smuzhiyun 	 * to generate branch sample for the instruction range before the
1509*4882a593Smuzhiyun 	 * exception is trapped to kernel or before the exception returning.
1510*4882a593Smuzhiyun 	 *
1511*4882a593Smuzhiyun 	 * The exception packet includes the dummy address values, so don't
1512*4882a593Smuzhiyun 	 * swap PACKET with PREV_PACKET.  This keeps PREV_PACKET to be useful
1513*4882a593Smuzhiyun 	 * for generating instruction and branch samples.
1514*4882a593Smuzhiyun 	 */
1515*4882a593Smuzhiyun 	if (tidq->prev_packet->sample_type == CS_ETM_RANGE)
1516*4882a593Smuzhiyun 		tidq->prev_packet->last_instr_taken_branch = true;
1517*4882a593Smuzhiyun 
1518*4882a593Smuzhiyun 	return 0;
1519*4882a593Smuzhiyun }
1520*4882a593Smuzhiyun 
cs_etm__flush(struct cs_etm_queue * etmq,struct cs_etm_traceid_queue * tidq)1521*4882a593Smuzhiyun static int cs_etm__flush(struct cs_etm_queue *etmq,
1522*4882a593Smuzhiyun 			 struct cs_etm_traceid_queue *tidq)
1523*4882a593Smuzhiyun {
1524*4882a593Smuzhiyun 	int err = 0;
1525*4882a593Smuzhiyun 	struct cs_etm_auxtrace *etm = etmq->etm;
1526*4882a593Smuzhiyun 
1527*4882a593Smuzhiyun 	/* Handle start tracing packet */
1528*4882a593Smuzhiyun 	if (tidq->prev_packet->sample_type == CS_ETM_EMPTY)
1529*4882a593Smuzhiyun 		goto swap_packet;
1530*4882a593Smuzhiyun 
1531*4882a593Smuzhiyun 	if (etmq->etm->synth_opts.last_branch &&
1532*4882a593Smuzhiyun 	    tidq->prev_packet->sample_type == CS_ETM_RANGE) {
1533*4882a593Smuzhiyun 		u64 addr;
1534*4882a593Smuzhiyun 
1535*4882a593Smuzhiyun 		/* Prepare last branches for instruction sample */
1536*4882a593Smuzhiyun 		cs_etm__copy_last_branch_rb(etmq, tidq);
1537*4882a593Smuzhiyun 
1538*4882a593Smuzhiyun 		/*
1539*4882a593Smuzhiyun 		 * Generate a last branch event for the branches left in the
1540*4882a593Smuzhiyun 		 * circular buffer at the end of the trace.
1541*4882a593Smuzhiyun 		 *
1542*4882a593Smuzhiyun 		 * Use the address of the end of the last reported execution
1543*4882a593Smuzhiyun 		 * range
1544*4882a593Smuzhiyun 		 */
1545*4882a593Smuzhiyun 		addr = cs_etm__last_executed_instr(tidq->prev_packet);
1546*4882a593Smuzhiyun 
1547*4882a593Smuzhiyun 		err = cs_etm__synth_instruction_sample(
1548*4882a593Smuzhiyun 			etmq, tidq, addr,
1549*4882a593Smuzhiyun 			tidq->period_instructions);
1550*4882a593Smuzhiyun 		if (err)
1551*4882a593Smuzhiyun 			return err;
1552*4882a593Smuzhiyun 
1553*4882a593Smuzhiyun 		tidq->period_instructions = 0;
1554*4882a593Smuzhiyun 
1555*4882a593Smuzhiyun 	}
1556*4882a593Smuzhiyun 
1557*4882a593Smuzhiyun 	if (etm->sample_branches &&
1558*4882a593Smuzhiyun 	    tidq->prev_packet->sample_type == CS_ETM_RANGE) {
1559*4882a593Smuzhiyun 		err = cs_etm__synth_branch_sample(etmq, tidq);
1560*4882a593Smuzhiyun 		if (err)
1561*4882a593Smuzhiyun 			return err;
1562*4882a593Smuzhiyun 	}
1563*4882a593Smuzhiyun 
1564*4882a593Smuzhiyun swap_packet:
1565*4882a593Smuzhiyun 	cs_etm__packet_swap(etm, tidq);
1566*4882a593Smuzhiyun 
1567*4882a593Smuzhiyun 	/* Reset last branches after flush the trace */
1568*4882a593Smuzhiyun 	if (etm->synth_opts.last_branch)
1569*4882a593Smuzhiyun 		cs_etm__reset_last_branch_rb(tidq);
1570*4882a593Smuzhiyun 
1571*4882a593Smuzhiyun 	return err;
1572*4882a593Smuzhiyun }
1573*4882a593Smuzhiyun 
cs_etm__end_block(struct cs_etm_queue * etmq,struct cs_etm_traceid_queue * tidq)1574*4882a593Smuzhiyun static int cs_etm__end_block(struct cs_etm_queue *etmq,
1575*4882a593Smuzhiyun 			     struct cs_etm_traceid_queue *tidq)
1576*4882a593Smuzhiyun {
1577*4882a593Smuzhiyun 	int err;
1578*4882a593Smuzhiyun 
1579*4882a593Smuzhiyun 	/*
1580*4882a593Smuzhiyun 	 * It has no new packet coming and 'etmq->packet' contains the stale
1581*4882a593Smuzhiyun 	 * packet which was set at the previous time with packets swapping;
1582*4882a593Smuzhiyun 	 * so skip to generate branch sample to avoid stale packet.
1583*4882a593Smuzhiyun 	 *
1584*4882a593Smuzhiyun 	 * For this case only flush branch stack and generate a last branch
1585*4882a593Smuzhiyun 	 * event for the branches left in the circular buffer at the end of
1586*4882a593Smuzhiyun 	 * the trace.
1587*4882a593Smuzhiyun 	 */
1588*4882a593Smuzhiyun 	if (etmq->etm->synth_opts.last_branch &&
1589*4882a593Smuzhiyun 	    tidq->prev_packet->sample_type == CS_ETM_RANGE) {
1590*4882a593Smuzhiyun 		u64 addr;
1591*4882a593Smuzhiyun 
1592*4882a593Smuzhiyun 		/* Prepare last branches for instruction sample */
1593*4882a593Smuzhiyun 		cs_etm__copy_last_branch_rb(etmq, tidq);
1594*4882a593Smuzhiyun 
1595*4882a593Smuzhiyun 		/*
1596*4882a593Smuzhiyun 		 * Use the address of the end of the last reported execution
1597*4882a593Smuzhiyun 		 * range.
1598*4882a593Smuzhiyun 		 */
1599*4882a593Smuzhiyun 		addr = cs_etm__last_executed_instr(tidq->prev_packet);
1600*4882a593Smuzhiyun 
1601*4882a593Smuzhiyun 		err = cs_etm__synth_instruction_sample(
1602*4882a593Smuzhiyun 			etmq, tidq, addr,
1603*4882a593Smuzhiyun 			tidq->period_instructions);
1604*4882a593Smuzhiyun 		if (err)
1605*4882a593Smuzhiyun 			return err;
1606*4882a593Smuzhiyun 
1607*4882a593Smuzhiyun 		tidq->period_instructions = 0;
1608*4882a593Smuzhiyun 	}
1609*4882a593Smuzhiyun 
1610*4882a593Smuzhiyun 	return 0;
1611*4882a593Smuzhiyun }
1612*4882a593Smuzhiyun /*
1613*4882a593Smuzhiyun  * cs_etm__get_data_block: Fetch a block from the auxtrace_buffer queue
1614*4882a593Smuzhiyun  *			   if need be.
1615*4882a593Smuzhiyun  * Returns:	< 0	if error
1616*4882a593Smuzhiyun  *		= 0	if no more auxtrace_buffer to read
1617*4882a593Smuzhiyun  *		> 0	if the current buffer isn't empty yet
1618*4882a593Smuzhiyun  */
cs_etm__get_data_block(struct cs_etm_queue * etmq)1619*4882a593Smuzhiyun static int cs_etm__get_data_block(struct cs_etm_queue *etmq)
1620*4882a593Smuzhiyun {
1621*4882a593Smuzhiyun 	int ret;
1622*4882a593Smuzhiyun 
1623*4882a593Smuzhiyun 	if (!etmq->buf_len) {
1624*4882a593Smuzhiyun 		ret = cs_etm__get_trace(etmq);
1625*4882a593Smuzhiyun 		if (ret <= 0)
1626*4882a593Smuzhiyun 			return ret;
1627*4882a593Smuzhiyun 		/*
1628*4882a593Smuzhiyun 		 * We cannot assume consecutive blocks in the data file
1629*4882a593Smuzhiyun 		 * are contiguous, reset the decoder to force re-sync.
1630*4882a593Smuzhiyun 		 */
1631*4882a593Smuzhiyun 		ret = cs_etm_decoder__reset(etmq->decoder);
1632*4882a593Smuzhiyun 		if (ret)
1633*4882a593Smuzhiyun 			return ret;
1634*4882a593Smuzhiyun 	}
1635*4882a593Smuzhiyun 
1636*4882a593Smuzhiyun 	return etmq->buf_len;
1637*4882a593Smuzhiyun }
1638*4882a593Smuzhiyun 
cs_etm__is_svc_instr(struct cs_etm_queue * etmq,u8 trace_chan_id,struct cs_etm_packet * packet,u64 end_addr)1639*4882a593Smuzhiyun static bool cs_etm__is_svc_instr(struct cs_etm_queue *etmq, u8 trace_chan_id,
1640*4882a593Smuzhiyun 				 struct cs_etm_packet *packet,
1641*4882a593Smuzhiyun 				 u64 end_addr)
1642*4882a593Smuzhiyun {
1643*4882a593Smuzhiyun 	/* Initialise to keep compiler happy */
1644*4882a593Smuzhiyun 	u16 instr16 = 0;
1645*4882a593Smuzhiyun 	u32 instr32 = 0;
1646*4882a593Smuzhiyun 	u64 addr;
1647*4882a593Smuzhiyun 
1648*4882a593Smuzhiyun 	switch (packet->isa) {
1649*4882a593Smuzhiyun 	case CS_ETM_ISA_T32:
1650*4882a593Smuzhiyun 		/*
1651*4882a593Smuzhiyun 		 * The SVC of T32 is defined in ARM DDI 0487D.a, F5.1.247:
1652*4882a593Smuzhiyun 		 *
1653*4882a593Smuzhiyun 		 *  b'15         b'8
1654*4882a593Smuzhiyun 		 * +-----------------+--------+
1655*4882a593Smuzhiyun 		 * | 1 1 0 1 1 1 1 1 |  imm8  |
1656*4882a593Smuzhiyun 		 * +-----------------+--------+
1657*4882a593Smuzhiyun 		 *
1658*4882a593Smuzhiyun 		 * According to the specifiction, it only defines SVC for T32
1659*4882a593Smuzhiyun 		 * with 16 bits instruction and has no definition for 32bits;
1660*4882a593Smuzhiyun 		 * so below only read 2 bytes as instruction size for T32.
1661*4882a593Smuzhiyun 		 */
1662*4882a593Smuzhiyun 		addr = end_addr - 2;
1663*4882a593Smuzhiyun 		cs_etm__mem_access(etmq, trace_chan_id, addr,
1664*4882a593Smuzhiyun 				   sizeof(instr16), (u8 *)&instr16);
1665*4882a593Smuzhiyun 		if ((instr16 & 0xFF00) == 0xDF00)
1666*4882a593Smuzhiyun 			return true;
1667*4882a593Smuzhiyun 
1668*4882a593Smuzhiyun 		break;
1669*4882a593Smuzhiyun 	case CS_ETM_ISA_A32:
1670*4882a593Smuzhiyun 		/*
1671*4882a593Smuzhiyun 		 * The SVC of A32 is defined in ARM DDI 0487D.a, F5.1.247:
1672*4882a593Smuzhiyun 		 *
1673*4882a593Smuzhiyun 		 *  b'31 b'28 b'27 b'24
1674*4882a593Smuzhiyun 		 * +---------+---------+-------------------------+
1675*4882a593Smuzhiyun 		 * |  !1111  | 1 1 1 1 |        imm24            |
1676*4882a593Smuzhiyun 		 * +---------+---------+-------------------------+
1677*4882a593Smuzhiyun 		 */
1678*4882a593Smuzhiyun 		addr = end_addr - 4;
1679*4882a593Smuzhiyun 		cs_etm__mem_access(etmq, trace_chan_id, addr,
1680*4882a593Smuzhiyun 				   sizeof(instr32), (u8 *)&instr32);
1681*4882a593Smuzhiyun 		if ((instr32 & 0x0F000000) == 0x0F000000 &&
1682*4882a593Smuzhiyun 		    (instr32 & 0xF0000000) != 0xF0000000)
1683*4882a593Smuzhiyun 			return true;
1684*4882a593Smuzhiyun 
1685*4882a593Smuzhiyun 		break;
1686*4882a593Smuzhiyun 	case CS_ETM_ISA_A64:
1687*4882a593Smuzhiyun 		/*
1688*4882a593Smuzhiyun 		 * The SVC of A64 is defined in ARM DDI 0487D.a, C6.2.294:
1689*4882a593Smuzhiyun 		 *
1690*4882a593Smuzhiyun 		 *  b'31               b'21           b'4     b'0
1691*4882a593Smuzhiyun 		 * +-----------------------+---------+-----------+
1692*4882a593Smuzhiyun 		 * | 1 1 0 1 0 1 0 0 0 0 0 |  imm16  | 0 0 0 0 1 |
1693*4882a593Smuzhiyun 		 * +-----------------------+---------+-----------+
1694*4882a593Smuzhiyun 		 */
1695*4882a593Smuzhiyun 		addr = end_addr - 4;
1696*4882a593Smuzhiyun 		cs_etm__mem_access(etmq, trace_chan_id, addr,
1697*4882a593Smuzhiyun 				   sizeof(instr32), (u8 *)&instr32);
1698*4882a593Smuzhiyun 		if ((instr32 & 0xFFE0001F) == 0xd4000001)
1699*4882a593Smuzhiyun 			return true;
1700*4882a593Smuzhiyun 
1701*4882a593Smuzhiyun 		break;
1702*4882a593Smuzhiyun 	case CS_ETM_ISA_UNKNOWN:
1703*4882a593Smuzhiyun 	default:
1704*4882a593Smuzhiyun 		break;
1705*4882a593Smuzhiyun 	}
1706*4882a593Smuzhiyun 
1707*4882a593Smuzhiyun 	return false;
1708*4882a593Smuzhiyun }
1709*4882a593Smuzhiyun 
cs_etm__is_syscall(struct cs_etm_queue * etmq,struct cs_etm_traceid_queue * tidq,u64 magic)1710*4882a593Smuzhiyun static bool cs_etm__is_syscall(struct cs_etm_queue *etmq,
1711*4882a593Smuzhiyun 			       struct cs_etm_traceid_queue *tidq, u64 magic)
1712*4882a593Smuzhiyun {
1713*4882a593Smuzhiyun 	u8 trace_chan_id = tidq->trace_chan_id;
1714*4882a593Smuzhiyun 	struct cs_etm_packet *packet = tidq->packet;
1715*4882a593Smuzhiyun 	struct cs_etm_packet *prev_packet = tidq->prev_packet;
1716*4882a593Smuzhiyun 
1717*4882a593Smuzhiyun 	if (magic == __perf_cs_etmv3_magic)
1718*4882a593Smuzhiyun 		if (packet->exception_number == CS_ETMV3_EXC_SVC)
1719*4882a593Smuzhiyun 			return true;
1720*4882a593Smuzhiyun 
1721*4882a593Smuzhiyun 	/*
1722*4882a593Smuzhiyun 	 * ETMv4 exception type CS_ETMV4_EXC_CALL covers SVC, SMC and
1723*4882a593Smuzhiyun 	 * HVC cases; need to check if it's SVC instruction based on
1724*4882a593Smuzhiyun 	 * packet address.
1725*4882a593Smuzhiyun 	 */
1726*4882a593Smuzhiyun 	if (magic == __perf_cs_etmv4_magic) {
1727*4882a593Smuzhiyun 		if (packet->exception_number == CS_ETMV4_EXC_CALL &&
1728*4882a593Smuzhiyun 		    cs_etm__is_svc_instr(etmq, trace_chan_id, prev_packet,
1729*4882a593Smuzhiyun 					 prev_packet->end_addr))
1730*4882a593Smuzhiyun 			return true;
1731*4882a593Smuzhiyun 	}
1732*4882a593Smuzhiyun 
1733*4882a593Smuzhiyun 	return false;
1734*4882a593Smuzhiyun }
1735*4882a593Smuzhiyun 
cs_etm__is_async_exception(struct cs_etm_traceid_queue * tidq,u64 magic)1736*4882a593Smuzhiyun static bool cs_etm__is_async_exception(struct cs_etm_traceid_queue *tidq,
1737*4882a593Smuzhiyun 				       u64 magic)
1738*4882a593Smuzhiyun {
1739*4882a593Smuzhiyun 	struct cs_etm_packet *packet = tidq->packet;
1740*4882a593Smuzhiyun 
1741*4882a593Smuzhiyun 	if (magic == __perf_cs_etmv3_magic)
1742*4882a593Smuzhiyun 		if (packet->exception_number == CS_ETMV3_EXC_DEBUG_HALT ||
1743*4882a593Smuzhiyun 		    packet->exception_number == CS_ETMV3_EXC_ASYNC_DATA_ABORT ||
1744*4882a593Smuzhiyun 		    packet->exception_number == CS_ETMV3_EXC_PE_RESET ||
1745*4882a593Smuzhiyun 		    packet->exception_number == CS_ETMV3_EXC_IRQ ||
1746*4882a593Smuzhiyun 		    packet->exception_number == CS_ETMV3_EXC_FIQ)
1747*4882a593Smuzhiyun 			return true;
1748*4882a593Smuzhiyun 
1749*4882a593Smuzhiyun 	if (magic == __perf_cs_etmv4_magic)
1750*4882a593Smuzhiyun 		if (packet->exception_number == CS_ETMV4_EXC_RESET ||
1751*4882a593Smuzhiyun 		    packet->exception_number == CS_ETMV4_EXC_DEBUG_HALT ||
1752*4882a593Smuzhiyun 		    packet->exception_number == CS_ETMV4_EXC_SYSTEM_ERROR ||
1753*4882a593Smuzhiyun 		    packet->exception_number == CS_ETMV4_EXC_INST_DEBUG ||
1754*4882a593Smuzhiyun 		    packet->exception_number == CS_ETMV4_EXC_DATA_DEBUG ||
1755*4882a593Smuzhiyun 		    packet->exception_number == CS_ETMV4_EXC_IRQ ||
1756*4882a593Smuzhiyun 		    packet->exception_number == CS_ETMV4_EXC_FIQ)
1757*4882a593Smuzhiyun 			return true;
1758*4882a593Smuzhiyun 
1759*4882a593Smuzhiyun 	return false;
1760*4882a593Smuzhiyun }
1761*4882a593Smuzhiyun 
cs_etm__is_sync_exception(struct cs_etm_queue * etmq,struct cs_etm_traceid_queue * tidq,u64 magic)1762*4882a593Smuzhiyun static bool cs_etm__is_sync_exception(struct cs_etm_queue *etmq,
1763*4882a593Smuzhiyun 				      struct cs_etm_traceid_queue *tidq,
1764*4882a593Smuzhiyun 				      u64 magic)
1765*4882a593Smuzhiyun {
1766*4882a593Smuzhiyun 	u8 trace_chan_id = tidq->trace_chan_id;
1767*4882a593Smuzhiyun 	struct cs_etm_packet *packet = tidq->packet;
1768*4882a593Smuzhiyun 	struct cs_etm_packet *prev_packet = tidq->prev_packet;
1769*4882a593Smuzhiyun 
1770*4882a593Smuzhiyun 	if (magic == __perf_cs_etmv3_magic)
1771*4882a593Smuzhiyun 		if (packet->exception_number == CS_ETMV3_EXC_SMC ||
1772*4882a593Smuzhiyun 		    packet->exception_number == CS_ETMV3_EXC_HYP ||
1773*4882a593Smuzhiyun 		    packet->exception_number == CS_ETMV3_EXC_JAZELLE_THUMBEE ||
1774*4882a593Smuzhiyun 		    packet->exception_number == CS_ETMV3_EXC_UNDEFINED_INSTR ||
1775*4882a593Smuzhiyun 		    packet->exception_number == CS_ETMV3_EXC_PREFETCH_ABORT ||
1776*4882a593Smuzhiyun 		    packet->exception_number == CS_ETMV3_EXC_DATA_FAULT ||
1777*4882a593Smuzhiyun 		    packet->exception_number == CS_ETMV3_EXC_GENERIC)
1778*4882a593Smuzhiyun 			return true;
1779*4882a593Smuzhiyun 
1780*4882a593Smuzhiyun 	if (magic == __perf_cs_etmv4_magic) {
1781*4882a593Smuzhiyun 		if (packet->exception_number == CS_ETMV4_EXC_TRAP ||
1782*4882a593Smuzhiyun 		    packet->exception_number == CS_ETMV4_EXC_ALIGNMENT ||
1783*4882a593Smuzhiyun 		    packet->exception_number == CS_ETMV4_EXC_INST_FAULT ||
1784*4882a593Smuzhiyun 		    packet->exception_number == CS_ETMV4_EXC_DATA_FAULT)
1785*4882a593Smuzhiyun 			return true;
1786*4882a593Smuzhiyun 
1787*4882a593Smuzhiyun 		/*
1788*4882a593Smuzhiyun 		 * For CS_ETMV4_EXC_CALL, except SVC other instructions
1789*4882a593Smuzhiyun 		 * (SMC, HVC) are taken as sync exceptions.
1790*4882a593Smuzhiyun 		 */
1791*4882a593Smuzhiyun 		if (packet->exception_number == CS_ETMV4_EXC_CALL &&
1792*4882a593Smuzhiyun 		    !cs_etm__is_svc_instr(etmq, trace_chan_id, prev_packet,
1793*4882a593Smuzhiyun 					  prev_packet->end_addr))
1794*4882a593Smuzhiyun 			return true;
1795*4882a593Smuzhiyun 
1796*4882a593Smuzhiyun 		/*
1797*4882a593Smuzhiyun 		 * ETMv4 has 5 bits for exception number; if the numbers
1798*4882a593Smuzhiyun 		 * are in the range ( CS_ETMV4_EXC_FIQ, CS_ETMV4_EXC_END ]
1799*4882a593Smuzhiyun 		 * they are implementation defined exceptions.
1800*4882a593Smuzhiyun 		 *
1801*4882a593Smuzhiyun 		 * For this case, simply take it as sync exception.
1802*4882a593Smuzhiyun 		 */
1803*4882a593Smuzhiyun 		if (packet->exception_number > CS_ETMV4_EXC_FIQ &&
1804*4882a593Smuzhiyun 		    packet->exception_number <= CS_ETMV4_EXC_END)
1805*4882a593Smuzhiyun 			return true;
1806*4882a593Smuzhiyun 	}
1807*4882a593Smuzhiyun 
1808*4882a593Smuzhiyun 	return false;
1809*4882a593Smuzhiyun }
1810*4882a593Smuzhiyun 
cs_etm__set_sample_flags(struct cs_etm_queue * etmq,struct cs_etm_traceid_queue * tidq)1811*4882a593Smuzhiyun static int cs_etm__set_sample_flags(struct cs_etm_queue *etmq,
1812*4882a593Smuzhiyun 				    struct cs_etm_traceid_queue *tidq)
1813*4882a593Smuzhiyun {
1814*4882a593Smuzhiyun 	struct cs_etm_packet *packet = tidq->packet;
1815*4882a593Smuzhiyun 	struct cs_etm_packet *prev_packet = tidq->prev_packet;
1816*4882a593Smuzhiyun 	u8 trace_chan_id = tidq->trace_chan_id;
1817*4882a593Smuzhiyun 	u64 magic;
1818*4882a593Smuzhiyun 	int ret;
1819*4882a593Smuzhiyun 
1820*4882a593Smuzhiyun 	switch (packet->sample_type) {
1821*4882a593Smuzhiyun 	case CS_ETM_RANGE:
1822*4882a593Smuzhiyun 		/*
1823*4882a593Smuzhiyun 		 * Immediate branch instruction without neither link nor
1824*4882a593Smuzhiyun 		 * return flag, it's normal branch instruction within
1825*4882a593Smuzhiyun 		 * the function.
1826*4882a593Smuzhiyun 		 */
1827*4882a593Smuzhiyun 		if (packet->last_instr_type == OCSD_INSTR_BR &&
1828*4882a593Smuzhiyun 		    packet->last_instr_subtype == OCSD_S_INSTR_NONE) {
1829*4882a593Smuzhiyun 			packet->flags = PERF_IP_FLAG_BRANCH;
1830*4882a593Smuzhiyun 
1831*4882a593Smuzhiyun 			if (packet->last_instr_cond)
1832*4882a593Smuzhiyun 				packet->flags |= PERF_IP_FLAG_CONDITIONAL;
1833*4882a593Smuzhiyun 		}
1834*4882a593Smuzhiyun 
1835*4882a593Smuzhiyun 		/*
1836*4882a593Smuzhiyun 		 * Immediate branch instruction with link (e.g. BL), this is
1837*4882a593Smuzhiyun 		 * branch instruction for function call.
1838*4882a593Smuzhiyun 		 */
1839*4882a593Smuzhiyun 		if (packet->last_instr_type == OCSD_INSTR_BR &&
1840*4882a593Smuzhiyun 		    packet->last_instr_subtype == OCSD_S_INSTR_BR_LINK)
1841*4882a593Smuzhiyun 			packet->flags = PERF_IP_FLAG_BRANCH |
1842*4882a593Smuzhiyun 					PERF_IP_FLAG_CALL;
1843*4882a593Smuzhiyun 
1844*4882a593Smuzhiyun 		/*
1845*4882a593Smuzhiyun 		 * Indirect branch instruction with link (e.g. BLR), this is
1846*4882a593Smuzhiyun 		 * branch instruction for function call.
1847*4882a593Smuzhiyun 		 */
1848*4882a593Smuzhiyun 		if (packet->last_instr_type == OCSD_INSTR_BR_INDIRECT &&
1849*4882a593Smuzhiyun 		    packet->last_instr_subtype == OCSD_S_INSTR_BR_LINK)
1850*4882a593Smuzhiyun 			packet->flags = PERF_IP_FLAG_BRANCH |
1851*4882a593Smuzhiyun 					PERF_IP_FLAG_CALL;
1852*4882a593Smuzhiyun 
1853*4882a593Smuzhiyun 		/*
1854*4882a593Smuzhiyun 		 * Indirect branch instruction with subtype of
1855*4882a593Smuzhiyun 		 * OCSD_S_INSTR_V7_IMPLIED_RET, this is explicit hint for
1856*4882a593Smuzhiyun 		 * function return for A32/T32.
1857*4882a593Smuzhiyun 		 */
1858*4882a593Smuzhiyun 		if (packet->last_instr_type == OCSD_INSTR_BR_INDIRECT &&
1859*4882a593Smuzhiyun 		    packet->last_instr_subtype == OCSD_S_INSTR_V7_IMPLIED_RET)
1860*4882a593Smuzhiyun 			packet->flags = PERF_IP_FLAG_BRANCH |
1861*4882a593Smuzhiyun 					PERF_IP_FLAG_RETURN;
1862*4882a593Smuzhiyun 
1863*4882a593Smuzhiyun 		/*
1864*4882a593Smuzhiyun 		 * Indirect branch instruction without link (e.g. BR), usually
1865*4882a593Smuzhiyun 		 * this is used for function return, especially for functions
1866*4882a593Smuzhiyun 		 * within dynamic link lib.
1867*4882a593Smuzhiyun 		 */
1868*4882a593Smuzhiyun 		if (packet->last_instr_type == OCSD_INSTR_BR_INDIRECT &&
1869*4882a593Smuzhiyun 		    packet->last_instr_subtype == OCSD_S_INSTR_NONE)
1870*4882a593Smuzhiyun 			packet->flags = PERF_IP_FLAG_BRANCH |
1871*4882a593Smuzhiyun 					PERF_IP_FLAG_RETURN;
1872*4882a593Smuzhiyun 
1873*4882a593Smuzhiyun 		/* Return instruction for function return. */
1874*4882a593Smuzhiyun 		if (packet->last_instr_type == OCSD_INSTR_BR_INDIRECT &&
1875*4882a593Smuzhiyun 		    packet->last_instr_subtype == OCSD_S_INSTR_V8_RET)
1876*4882a593Smuzhiyun 			packet->flags = PERF_IP_FLAG_BRANCH |
1877*4882a593Smuzhiyun 					PERF_IP_FLAG_RETURN;
1878*4882a593Smuzhiyun 
1879*4882a593Smuzhiyun 		/*
1880*4882a593Smuzhiyun 		 * Decoder might insert a discontinuity in the middle of
1881*4882a593Smuzhiyun 		 * instruction packets, fixup prev_packet with flag
1882*4882a593Smuzhiyun 		 * PERF_IP_FLAG_TRACE_BEGIN to indicate restarting trace.
1883*4882a593Smuzhiyun 		 */
1884*4882a593Smuzhiyun 		if (prev_packet->sample_type == CS_ETM_DISCONTINUITY)
1885*4882a593Smuzhiyun 			prev_packet->flags |= PERF_IP_FLAG_BRANCH |
1886*4882a593Smuzhiyun 					      PERF_IP_FLAG_TRACE_BEGIN;
1887*4882a593Smuzhiyun 
1888*4882a593Smuzhiyun 		/*
1889*4882a593Smuzhiyun 		 * If the previous packet is an exception return packet
1890*4882a593Smuzhiyun 		 * and the return address just follows SVC instuction,
1891*4882a593Smuzhiyun 		 * it needs to calibrate the previous packet sample flags
1892*4882a593Smuzhiyun 		 * as PERF_IP_FLAG_SYSCALLRET.
1893*4882a593Smuzhiyun 		 */
1894*4882a593Smuzhiyun 		if (prev_packet->flags == (PERF_IP_FLAG_BRANCH |
1895*4882a593Smuzhiyun 					   PERF_IP_FLAG_RETURN |
1896*4882a593Smuzhiyun 					   PERF_IP_FLAG_INTERRUPT) &&
1897*4882a593Smuzhiyun 		    cs_etm__is_svc_instr(etmq, trace_chan_id,
1898*4882a593Smuzhiyun 					 packet, packet->start_addr))
1899*4882a593Smuzhiyun 			prev_packet->flags = PERF_IP_FLAG_BRANCH |
1900*4882a593Smuzhiyun 					     PERF_IP_FLAG_RETURN |
1901*4882a593Smuzhiyun 					     PERF_IP_FLAG_SYSCALLRET;
1902*4882a593Smuzhiyun 		break;
1903*4882a593Smuzhiyun 	case CS_ETM_DISCONTINUITY:
1904*4882a593Smuzhiyun 		/*
1905*4882a593Smuzhiyun 		 * The trace is discontinuous, if the previous packet is
1906*4882a593Smuzhiyun 		 * instruction packet, set flag PERF_IP_FLAG_TRACE_END
1907*4882a593Smuzhiyun 		 * for previous packet.
1908*4882a593Smuzhiyun 		 */
1909*4882a593Smuzhiyun 		if (prev_packet->sample_type == CS_ETM_RANGE)
1910*4882a593Smuzhiyun 			prev_packet->flags |= PERF_IP_FLAG_BRANCH |
1911*4882a593Smuzhiyun 					      PERF_IP_FLAG_TRACE_END;
1912*4882a593Smuzhiyun 		break;
1913*4882a593Smuzhiyun 	case CS_ETM_EXCEPTION:
1914*4882a593Smuzhiyun 		ret = cs_etm__get_magic(packet->trace_chan_id, &magic);
1915*4882a593Smuzhiyun 		if (ret)
1916*4882a593Smuzhiyun 			return ret;
1917*4882a593Smuzhiyun 
1918*4882a593Smuzhiyun 		/* The exception is for system call. */
1919*4882a593Smuzhiyun 		if (cs_etm__is_syscall(etmq, tidq, magic))
1920*4882a593Smuzhiyun 			packet->flags = PERF_IP_FLAG_BRANCH |
1921*4882a593Smuzhiyun 					PERF_IP_FLAG_CALL |
1922*4882a593Smuzhiyun 					PERF_IP_FLAG_SYSCALLRET;
1923*4882a593Smuzhiyun 		/*
1924*4882a593Smuzhiyun 		 * The exceptions are triggered by external signals from bus,
1925*4882a593Smuzhiyun 		 * interrupt controller, debug module, PE reset or halt.
1926*4882a593Smuzhiyun 		 */
1927*4882a593Smuzhiyun 		else if (cs_etm__is_async_exception(tidq, magic))
1928*4882a593Smuzhiyun 			packet->flags = PERF_IP_FLAG_BRANCH |
1929*4882a593Smuzhiyun 					PERF_IP_FLAG_CALL |
1930*4882a593Smuzhiyun 					PERF_IP_FLAG_ASYNC |
1931*4882a593Smuzhiyun 					PERF_IP_FLAG_INTERRUPT;
1932*4882a593Smuzhiyun 		/*
1933*4882a593Smuzhiyun 		 * Otherwise, exception is caused by trap, instruction &
1934*4882a593Smuzhiyun 		 * data fault, or alignment errors.
1935*4882a593Smuzhiyun 		 */
1936*4882a593Smuzhiyun 		else if (cs_etm__is_sync_exception(etmq, tidq, magic))
1937*4882a593Smuzhiyun 			packet->flags = PERF_IP_FLAG_BRANCH |
1938*4882a593Smuzhiyun 					PERF_IP_FLAG_CALL |
1939*4882a593Smuzhiyun 					PERF_IP_FLAG_INTERRUPT;
1940*4882a593Smuzhiyun 
1941*4882a593Smuzhiyun 		/*
1942*4882a593Smuzhiyun 		 * When the exception packet is inserted, since exception
1943*4882a593Smuzhiyun 		 * packet is not used standalone for generating samples
1944*4882a593Smuzhiyun 		 * and it's affiliation to the previous instruction range
1945*4882a593Smuzhiyun 		 * packet; so set previous range packet flags to tell perf
1946*4882a593Smuzhiyun 		 * it is an exception taken branch.
1947*4882a593Smuzhiyun 		 */
1948*4882a593Smuzhiyun 		if (prev_packet->sample_type == CS_ETM_RANGE)
1949*4882a593Smuzhiyun 			prev_packet->flags = packet->flags;
1950*4882a593Smuzhiyun 		break;
1951*4882a593Smuzhiyun 	case CS_ETM_EXCEPTION_RET:
1952*4882a593Smuzhiyun 		/*
1953*4882a593Smuzhiyun 		 * When the exception return packet is inserted, since
1954*4882a593Smuzhiyun 		 * exception return packet is not used standalone for
1955*4882a593Smuzhiyun 		 * generating samples and it's affiliation to the previous
1956*4882a593Smuzhiyun 		 * instruction range packet; so set previous range packet
1957*4882a593Smuzhiyun 		 * flags to tell perf it is an exception return branch.
1958*4882a593Smuzhiyun 		 *
1959*4882a593Smuzhiyun 		 * The exception return can be for either system call or
1960*4882a593Smuzhiyun 		 * other exception types; unfortunately the packet doesn't
1961*4882a593Smuzhiyun 		 * contain exception type related info so we cannot decide
1962*4882a593Smuzhiyun 		 * the exception type purely based on exception return packet.
1963*4882a593Smuzhiyun 		 * If we record the exception number from exception packet and
1964*4882a593Smuzhiyun 		 * reuse it for excpetion return packet, this is not reliable
1965*4882a593Smuzhiyun 		 * due the trace can be discontinuity or the interrupt can
1966*4882a593Smuzhiyun 		 * be nested, thus the recorded exception number cannot be
1967*4882a593Smuzhiyun 		 * used for exception return packet for these two cases.
1968*4882a593Smuzhiyun 		 *
1969*4882a593Smuzhiyun 		 * For exception return packet, we only need to distinguish the
1970*4882a593Smuzhiyun 		 * packet is for system call or for other types.  Thus the
1971*4882a593Smuzhiyun 		 * decision can be deferred when receive the next packet which
1972*4882a593Smuzhiyun 		 * contains the return address, based on the return address we
1973*4882a593Smuzhiyun 		 * can read out the previous instruction and check if it's a
1974*4882a593Smuzhiyun 		 * system call instruction and then calibrate the sample flag
1975*4882a593Smuzhiyun 		 * as needed.
1976*4882a593Smuzhiyun 		 */
1977*4882a593Smuzhiyun 		if (prev_packet->sample_type == CS_ETM_RANGE)
1978*4882a593Smuzhiyun 			prev_packet->flags = PERF_IP_FLAG_BRANCH |
1979*4882a593Smuzhiyun 					     PERF_IP_FLAG_RETURN |
1980*4882a593Smuzhiyun 					     PERF_IP_FLAG_INTERRUPT;
1981*4882a593Smuzhiyun 		break;
1982*4882a593Smuzhiyun 	case CS_ETM_EMPTY:
1983*4882a593Smuzhiyun 	default:
1984*4882a593Smuzhiyun 		break;
1985*4882a593Smuzhiyun 	}
1986*4882a593Smuzhiyun 
1987*4882a593Smuzhiyun 	return 0;
1988*4882a593Smuzhiyun }
1989*4882a593Smuzhiyun 
cs_etm__decode_data_block(struct cs_etm_queue * etmq)1990*4882a593Smuzhiyun static int cs_etm__decode_data_block(struct cs_etm_queue *etmq)
1991*4882a593Smuzhiyun {
1992*4882a593Smuzhiyun 	int ret = 0;
1993*4882a593Smuzhiyun 	size_t processed = 0;
1994*4882a593Smuzhiyun 
1995*4882a593Smuzhiyun 	/*
1996*4882a593Smuzhiyun 	 * Packets are decoded and added to the decoder's packet queue
1997*4882a593Smuzhiyun 	 * until the decoder packet processing callback has requested that
1998*4882a593Smuzhiyun 	 * processing stops or there is nothing left in the buffer.  Normal
1999*4882a593Smuzhiyun 	 * operations that stop processing are a timestamp packet or a full
2000*4882a593Smuzhiyun 	 * decoder buffer queue.
2001*4882a593Smuzhiyun 	 */
2002*4882a593Smuzhiyun 	ret = cs_etm_decoder__process_data_block(etmq->decoder,
2003*4882a593Smuzhiyun 						 etmq->offset,
2004*4882a593Smuzhiyun 						 &etmq->buf[etmq->buf_used],
2005*4882a593Smuzhiyun 						 etmq->buf_len,
2006*4882a593Smuzhiyun 						 &processed);
2007*4882a593Smuzhiyun 	if (ret)
2008*4882a593Smuzhiyun 		goto out;
2009*4882a593Smuzhiyun 
2010*4882a593Smuzhiyun 	etmq->offset += processed;
2011*4882a593Smuzhiyun 	etmq->buf_used += processed;
2012*4882a593Smuzhiyun 	etmq->buf_len -= processed;
2013*4882a593Smuzhiyun 
2014*4882a593Smuzhiyun out:
2015*4882a593Smuzhiyun 	return ret;
2016*4882a593Smuzhiyun }
2017*4882a593Smuzhiyun 
cs_etm__process_traceid_queue(struct cs_etm_queue * etmq,struct cs_etm_traceid_queue * tidq)2018*4882a593Smuzhiyun static int cs_etm__process_traceid_queue(struct cs_etm_queue *etmq,
2019*4882a593Smuzhiyun 					 struct cs_etm_traceid_queue *tidq)
2020*4882a593Smuzhiyun {
2021*4882a593Smuzhiyun 	int ret;
2022*4882a593Smuzhiyun 	struct cs_etm_packet_queue *packet_queue;
2023*4882a593Smuzhiyun 
2024*4882a593Smuzhiyun 	packet_queue = &tidq->packet_queue;
2025*4882a593Smuzhiyun 
2026*4882a593Smuzhiyun 	/* Process each packet in this chunk */
2027*4882a593Smuzhiyun 	while (1) {
2028*4882a593Smuzhiyun 		ret = cs_etm_decoder__get_packet(packet_queue,
2029*4882a593Smuzhiyun 						 tidq->packet);
2030*4882a593Smuzhiyun 		if (ret <= 0)
2031*4882a593Smuzhiyun 			/*
2032*4882a593Smuzhiyun 			 * Stop processing this chunk on
2033*4882a593Smuzhiyun 			 * end of data or error
2034*4882a593Smuzhiyun 			 */
2035*4882a593Smuzhiyun 			break;
2036*4882a593Smuzhiyun 
2037*4882a593Smuzhiyun 		/*
2038*4882a593Smuzhiyun 		 * Since packet addresses are swapped in packet
2039*4882a593Smuzhiyun 		 * handling within below switch() statements,
2040*4882a593Smuzhiyun 		 * thus setting sample flags must be called
2041*4882a593Smuzhiyun 		 * prior to switch() statement to use address
2042*4882a593Smuzhiyun 		 * information before packets swapping.
2043*4882a593Smuzhiyun 		 */
2044*4882a593Smuzhiyun 		ret = cs_etm__set_sample_flags(etmq, tidq);
2045*4882a593Smuzhiyun 		if (ret < 0)
2046*4882a593Smuzhiyun 			break;
2047*4882a593Smuzhiyun 
2048*4882a593Smuzhiyun 		switch (tidq->packet->sample_type) {
2049*4882a593Smuzhiyun 		case CS_ETM_RANGE:
2050*4882a593Smuzhiyun 			/*
2051*4882a593Smuzhiyun 			 * If the packet contains an instruction
2052*4882a593Smuzhiyun 			 * range, generate instruction sequence
2053*4882a593Smuzhiyun 			 * events.
2054*4882a593Smuzhiyun 			 */
2055*4882a593Smuzhiyun 			cs_etm__sample(etmq, tidq);
2056*4882a593Smuzhiyun 			break;
2057*4882a593Smuzhiyun 		case CS_ETM_EXCEPTION:
2058*4882a593Smuzhiyun 		case CS_ETM_EXCEPTION_RET:
2059*4882a593Smuzhiyun 			/*
2060*4882a593Smuzhiyun 			 * If the exception packet is coming,
2061*4882a593Smuzhiyun 			 * make sure the previous instruction
2062*4882a593Smuzhiyun 			 * range packet to be handled properly.
2063*4882a593Smuzhiyun 			 */
2064*4882a593Smuzhiyun 			cs_etm__exception(tidq);
2065*4882a593Smuzhiyun 			break;
2066*4882a593Smuzhiyun 		case CS_ETM_DISCONTINUITY:
2067*4882a593Smuzhiyun 			/*
2068*4882a593Smuzhiyun 			 * Discontinuity in trace, flush
2069*4882a593Smuzhiyun 			 * previous branch stack
2070*4882a593Smuzhiyun 			 */
2071*4882a593Smuzhiyun 			cs_etm__flush(etmq, tidq);
2072*4882a593Smuzhiyun 			break;
2073*4882a593Smuzhiyun 		case CS_ETM_EMPTY:
2074*4882a593Smuzhiyun 			/*
2075*4882a593Smuzhiyun 			 * Should not receive empty packet,
2076*4882a593Smuzhiyun 			 * report error.
2077*4882a593Smuzhiyun 			 */
2078*4882a593Smuzhiyun 			pr_err("CS ETM Trace: empty packet\n");
2079*4882a593Smuzhiyun 			return -EINVAL;
2080*4882a593Smuzhiyun 		default:
2081*4882a593Smuzhiyun 			break;
2082*4882a593Smuzhiyun 		}
2083*4882a593Smuzhiyun 	}
2084*4882a593Smuzhiyun 
2085*4882a593Smuzhiyun 	return ret;
2086*4882a593Smuzhiyun }
2087*4882a593Smuzhiyun 
cs_etm__clear_all_traceid_queues(struct cs_etm_queue * etmq)2088*4882a593Smuzhiyun static void cs_etm__clear_all_traceid_queues(struct cs_etm_queue *etmq)
2089*4882a593Smuzhiyun {
2090*4882a593Smuzhiyun 	int idx;
2091*4882a593Smuzhiyun 	struct int_node *inode;
2092*4882a593Smuzhiyun 	struct cs_etm_traceid_queue *tidq;
2093*4882a593Smuzhiyun 	struct intlist *traceid_queues_list = etmq->traceid_queues_list;
2094*4882a593Smuzhiyun 
2095*4882a593Smuzhiyun 	intlist__for_each_entry(inode, traceid_queues_list) {
2096*4882a593Smuzhiyun 		idx = (int)(intptr_t)inode->priv;
2097*4882a593Smuzhiyun 		tidq = etmq->traceid_queues[idx];
2098*4882a593Smuzhiyun 
2099*4882a593Smuzhiyun 		/* Ignore return value */
2100*4882a593Smuzhiyun 		cs_etm__process_traceid_queue(etmq, tidq);
2101*4882a593Smuzhiyun 
2102*4882a593Smuzhiyun 		/*
2103*4882a593Smuzhiyun 		 * Generate an instruction sample with the remaining
2104*4882a593Smuzhiyun 		 * branchstack entries.
2105*4882a593Smuzhiyun 		 */
2106*4882a593Smuzhiyun 		cs_etm__flush(etmq, tidq);
2107*4882a593Smuzhiyun 	}
2108*4882a593Smuzhiyun }
2109*4882a593Smuzhiyun 
cs_etm__run_decoder(struct cs_etm_queue * etmq)2110*4882a593Smuzhiyun static int cs_etm__run_decoder(struct cs_etm_queue *etmq)
2111*4882a593Smuzhiyun {
2112*4882a593Smuzhiyun 	int err = 0;
2113*4882a593Smuzhiyun 	struct cs_etm_traceid_queue *tidq;
2114*4882a593Smuzhiyun 
2115*4882a593Smuzhiyun 	tidq = cs_etm__etmq_get_traceid_queue(etmq, CS_ETM_PER_THREAD_TRACEID);
2116*4882a593Smuzhiyun 	if (!tidq)
2117*4882a593Smuzhiyun 		return -EINVAL;
2118*4882a593Smuzhiyun 
2119*4882a593Smuzhiyun 	/* Go through each buffer in the queue and decode them one by one */
2120*4882a593Smuzhiyun 	while (1) {
2121*4882a593Smuzhiyun 		err = cs_etm__get_data_block(etmq);
2122*4882a593Smuzhiyun 		if (err <= 0)
2123*4882a593Smuzhiyun 			return err;
2124*4882a593Smuzhiyun 
2125*4882a593Smuzhiyun 		/* Run trace decoder until buffer consumed or end of trace */
2126*4882a593Smuzhiyun 		do {
2127*4882a593Smuzhiyun 			err = cs_etm__decode_data_block(etmq);
2128*4882a593Smuzhiyun 			if (err)
2129*4882a593Smuzhiyun 				return err;
2130*4882a593Smuzhiyun 
2131*4882a593Smuzhiyun 			/*
2132*4882a593Smuzhiyun 			 * Process each packet in this chunk, nothing to do if
2133*4882a593Smuzhiyun 			 * an error occurs other than hoping the next one will
2134*4882a593Smuzhiyun 			 * be better.
2135*4882a593Smuzhiyun 			 */
2136*4882a593Smuzhiyun 			err = cs_etm__process_traceid_queue(etmq, tidq);
2137*4882a593Smuzhiyun 
2138*4882a593Smuzhiyun 		} while (etmq->buf_len);
2139*4882a593Smuzhiyun 
2140*4882a593Smuzhiyun 		if (err == 0)
2141*4882a593Smuzhiyun 			/* Flush any remaining branch stack entries */
2142*4882a593Smuzhiyun 			err = cs_etm__end_block(etmq, tidq);
2143*4882a593Smuzhiyun 	}
2144*4882a593Smuzhiyun 
2145*4882a593Smuzhiyun 	return err;
2146*4882a593Smuzhiyun }
2147*4882a593Smuzhiyun 
cs_etm__process_timeless_queues(struct cs_etm_auxtrace * etm,pid_t tid)2148*4882a593Smuzhiyun static int cs_etm__process_timeless_queues(struct cs_etm_auxtrace *etm,
2149*4882a593Smuzhiyun 					   pid_t tid)
2150*4882a593Smuzhiyun {
2151*4882a593Smuzhiyun 	unsigned int i;
2152*4882a593Smuzhiyun 	struct auxtrace_queues *queues = &etm->queues;
2153*4882a593Smuzhiyun 
2154*4882a593Smuzhiyun 	for (i = 0; i < queues->nr_queues; i++) {
2155*4882a593Smuzhiyun 		struct auxtrace_queue *queue = &etm->queues.queue_array[i];
2156*4882a593Smuzhiyun 		struct cs_etm_queue *etmq = queue->priv;
2157*4882a593Smuzhiyun 		struct cs_etm_traceid_queue *tidq;
2158*4882a593Smuzhiyun 
2159*4882a593Smuzhiyun 		if (!etmq)
2160*4882a593Smuzhiyun 			continue;
2161*4882a593Smuzhiyun 
2162*4882a593Smuzhiyun 		tidq = cs_etm__etmq_get_traceid_queue(etmq,
2163*4882a593Smuzhiyun 						CS_ETM_PER_THREAD_TRACEID);
2164*4882a593Smuzhiyun 
2165*4882a593Smuzhiyun 		if (!tidq)
2166*4882a593Smuzhiyun 			continue;
2167*4882a593Smuzhiyun 
2168*4882a593Smuzhiyun 		if ((tid == -1) || (tidq->tid == tid)) {
2169*4882a593Smuzhiyun 			cs_etm__set_pid_tid_cpu(etm, tidq);
2170*4882a593Smuzhiyun 			cs_etm__run_decoder(etmq);
2171*4882a593Smuzhiyun 		}
2172*4882a593Smuzhiyun 	}
2173*4882a593Smuzhiyun 
2174*4882a593Smuzhiyun 	return 0;
2175*4882a593Smuzhiyun }
2176*4882a593Smuzhiyun 
cs_etm__process_queues(struct cs_etm_auxtrace * etm)2177*4882a593Smuzhiyun static int cs_etm__process_queues(struct cs_etm_auxtrace *etm)
2178*4882a593Smuzhiyun {
2179*4882a593Smuzhiyun 	int ret = 0;
2180*4882a593Smuzhiyun 	unsigned int cs_queue_nr, queue_nr;
2181*4882a593Smuzhiyun 	u8 trace_chan_id;
2182*4882a593Smuzhiyun 	u64 timestamp;
2183*4882a593Smuzhiyun 	struct auxtrace_queue *queue;
2184*4882a593Smuzhiyun 	struct cs_etm_queue *etmq;
2185*4882a593Smuzhiyun 	struct cs_etm_traceid_queue *tidq;
2186*4882a593Smuzhiyun 
2187*4882a593Smuzhiyun 	while (1) {
2188*4882a593Smuzhiyun 		if (!etm->heap.heap_cnt)
2189*4882a593Smuzhiyun 			goto out;
2190*4882a593Smuzhiyun 
2191*4882a593Smuzhiyun 		/* Take the entry at the top of the min heap */
2192*4882a593Smuzhiyun 		cs_queue_nr = etm->heap.heap_array[0].queue_nr;
2193*4882a593Smuzhiyun 		queue_nr = TO_QUEUE_NR(cs_queue_nr);
2194*4882a593Smuzhiyun 		trace_chan_id = TO_TRACE_CHAN_ID(cs_queue_nr);
2195*4882a593Smuzhiyun 		queue = &etm->queues.queue_array[queue_nr];
2196*4882a593Smuzhiyun 		etmq = queue->priv;
2197*4882a593Smuzhiyun 
2198*4882a593Smuzhiyun 		/*
2199*4882a593Smuzhiyun 		 * Remove the top entry from the heap since we are about
2200*4882a593Smuzhiyun 		 * to process it.
2201*4882a593Smuzhiyun 		 */
2202*4882a593Smuzhiyun 		auxtrace_heap__pop(&etm->heap);
2203*4882a593Smuzhiyun 
2204*4882a593Smuzhiyun 		tidq  = cs_etm__etmq_get_traceid_queue(etmq, trace_chan_id);
2205*4882a593Smuzhiyun 		if (!tidq) {
2206*4882a593Smuzhiyun 			/*
2207*4882a593Smuzhiyun 			 * No traceID queue has been allocated for this traceID,
2208*4882a593Smuzhiyun 			 * which means something somewhere went very wrong.  No
2209*4882a593Smuzhiyun 			 * other choice than simply exit.
2210*4882a593Smuzhiyun 			 */
2211*4882a593Smuzhiyun 			ret = -EINVAL;
2212*4882a593Smuzhiyun 			goto out;
2213*4882a593Smuzhiyun 		}
2214*4882a593Smuzhiyun 
2215*4882a593Smuzhiyun 		/*
2216*4882a593Smuzhiyun 		 * Packets associated with this timestamp are already in
2217*4882a593Smuzhiyun 		 * the etmq's traceID queue, so process them.
2218*4882a593Smuzhiyun 		 */
2219*4882a593Smuzhiyun 		ret = cs_etm__process_traceid_queue(etmq, tidq);
2220*4882a593Smuzhiyun 		if (ret < 0)
2221*4882a593Smuzhiyun 			goto out;
2222*4882a593Smuzhiyun 
2223*4882a593Smuzhiyun 		/*
2224*4882a593Smuzhiyun 		 * Packets for this timestamp have been processed, time to
2225*4882a593Smuzhiyun 		 * move on to the next timestamp, fetching a new auxtrace_buffer
2226*4882a593Smuzhiyun 		 * if need be.
2227*4882a593Smuzhiyun 		 */
2228*4882a593Smuzhiyun refetch:
2229*4882a593Smuzhiyun 		ret = cs_etm__get_data_block(etmq);
2230*4882a593Smuzhiyun 		if (ret < 0)
2231*4882a593Smuzhiyun 			goto out;
2232*4882a593Smuzhiyun 
2233*4882a593Smuzhiyun 		/*
2234*4882a593Smuzhiyun 		 * No more auxtrace_buffers to process in this etmq, simply
2235*4882a593Smuzhiyun 		 * move on to another entry in the auxtrace_heap.
2236*4882a593Smuzhiyun 		 */
2237*4882a593Smuzhiyun 		if (!ret)
2238*4882a593Smuzhiyun 			continue;
2239*4882a593Smuzhiyun 
2240*4882a593Smuzhiyun 		ret = cs_etm__decode_data_block(etmq);
2241*4882a593Smuzhiyun 		if (ret)
2242*4882a593Smuzhiyun 			goto out;
2243*4882a593Smuzhiyun 
2244*4882a593Smuzhiyun 		timestamp = cs_etm__etmq_get_timestamp(etmq, &trace_chan_id);
2245*4882a593Smuzhiyun 
2246*4882a593Smuzhiyun 		if (!timestamp) {
2247*4882a593Smuzhiyun 			/*
2248*4882a593Smuzhiyun 			 * Function cs_etm__decode_data_block() returns when
2249*4882a593Smuzhiyun 			 * there is no more traces to decode in the current
2250*4882a593Smuzhiyun 			 * auxtrace_buffer OR when a timestamp has been
2251*4882a593Smuzhiyun 			 * encountered on any of the traceID queues.  Since we
2252*4882a593Smuzhiyun 			 * did not get a timestamp, there is no more traces to
2253*4882a593Smuzhiyun 			 * process in this auxtrace_buffer.  As such empty and
2254*4882a593Smuzhiyun 			 * flush all traceID queues.
2255*4882a593Smuzhiyun 			 */
2256*4882a593Smuzhiyun 			cs_etm__clear_all_traceid_queues(etmq);
2257*4882a593Smuzhiyun 
2258*4882a593Smuzhiyun 			/* Fetch another auxtrace_buffer for this etmq */
2259*4882a593Smuzhiyun 			goto refetch;
2260*4882a593Smuzhiyun 		}
2261*4882a593Smuzhiyun 
2262*4882a593Smuzhiyun 		/*
2263*4882a593Smuzhiyun 		 * Add to the min heap the timestamp for packets that have
2264*4882a593Smuzhiyun 		 * just been decoded.  They will be processed and synthesized
2265*4882a593Smuzhiyun 		 * during the next call to cs_etm__process_traceid_queue() for
2266*4882a593Smuzhiyun 		 * this queue/traceID.
2267*4882a593Smuzhiyun 		 */
2268*4882a593Smuzhiyun 		cs_queue_nr = TO_CS_QUEUE_NR(queue_nr, trace_chan_id);
2269*4882a593Smuzhiyun 		ret = auxtrace_heap__add(&etm->heap, cs_queue_nr, timestamp);
2270*4882a593Smuzhiyun 	}
2271*4882a593Smuzhiyun 
2272*4882a593Smuzhiyun out:
2273*4882a593Smuzhiyun 	return ret;
2274*4882a593Smuzhiyun }
2275*4882a593Smuzhiyun 
cs_etm__process_itrace_start(struct cs_etm_auxtrace * etm,union perf_event * event)2276*4882a593Smuzhiyun static int cs_etm__process_itrace_start(struct cs_etm_auxtrace *etm,
2277*4882a593Smuzhiyun 					union perf_event *event)
2278*4882a593Smuzhiyun {
2279*4882a593Smuzhiyun 	struct thread *th;
2280*4882a593Smuzhiyun 
2281*4882a593Smuzhiyun 	if (etm->timeless_decoding)
2282*4882a593Smuzhiyun 		return 0;
2283*4882a593Smuzhiyun 
2284*4882a593Smuzhiyun 	/*
2285*4882a593Smuzhiyun 	 * Add the tid/pid to the log so that we can get a match when
2286*4882a593Smuzhiyun 	 * we get a contextID from the decoder.
2287*4882a593Smuzhiyun 	 */
2288*4882a593Smuzhiyun 	th = machine__findnew_thread(etm->machine,
2289*4882a593Smuzhiyun 				     event->itrace_start.pid,
2290*4882a593Smuzhiyun 				     event->itrace_start.tid);
2291*4882a593Smuzhiyun 	if (!th)
2292*4882a593Smuzhiyun 		return -ENOMEM;
2293*4882a593Smuzhiyun 
2294*4882a593Smuzhiyun 	thread__put(th);
2295*4882a593Smuzhiyun 
2296*4882a593Smuzhiyun 	return 0;
2297*4882a593Smuzhiyun }
2298*4882a593Smuzhiyun 
cs_etm__process_switch_cpu_wide(struct cs_etm_auxtrace * etm,union perf_event * event)2299*4882a593Smuzhiyun static int cs_etm__process_switch_cpu_wide(struct cs_etm_auxtrace *etm,
2300*4882a593Smuzhiyun 					   union perf_event *event)
2301*4882a593Smuzhiyun {
2302*4882a593Smuzhiyun 	struct thread *th;
2303*4882a593Smuzhiyun 	bool out = event->header.misc & PERF_RECORD_MISC_SWITCH_OUT;
2304*4882a593Smuzhiyun 
2305*4882a593Smuzhiyun 	/*
2306*4882a593Smuzhiyun 	 * Context switch in per-thread mode are irrelevant since perf
2307*4882a593Smuzhiyun 	 * will start/stop tracing as the process is scheduled.
2308*4882a593Smuzhiyun 	 */
2309*4882a593Smuzhiyun 	if (etm->timeless_decoding)
2310*4882a593Smuzhiyun 		return 0;
2311*4882a593Smuzhiyun 
2312*4882a593Smuzhiyun 	/*
2313*4882a593Smuzhiyun 	 * SWITCH_IN events carry the next process to be switched out while
2314*4882a593Smuzhiyun 	 * SWITCH_OUT events carry the process to be switched in.  As such
2315*4882a593Smuzhiyun 	 * we don't care about IN events.
2316*4882a593Smuzhiyun 	 */
2317*4882a593Smuzhiyun 	if (!out)
2318*4882a593Smuzhiyun 		return 0;
2319*4882a593Smuzhiyun 
2320*4882a593Smuzhiyun 	/*
2321*4882a593Smuzhiyun 	 * Add the tid/pid to the log so that we can get a match when
2322*4882a593Smuzhiyun 	 * we get a contextID from the decoder.
2323*4882a593Smuzhiyun 	 */
2324*4882a593Smuzhiyun 	th = machine__findnew_thread(etm->machine,
2325*4882a593Smuzhiyun 				     event->context_switch.next_prev_pid,
2326*4882a593Smuzhiyun 				     event->context_switch.next_prev_tid);
2327*4882a593Smuzhiyun 	if (!th)
2328*4882a593Smuzhiyun 		return -ENOMEM;
2329*4882a593Smuzhiyun 
2330*4882a593Smuzhiyun 	thread__put(th);
2331*4882a593Smuzhiyun 
2332*4882a593Smuzhiyun 	return 0;
2333*4882a593Smuzhiyun }
2334*4882a593Smuzhiyun 
cs_etm__process_event(struct perf_session * session,union perf_event * event,struct perf_sample * sample,struct perf_tool * tool)2335*4882a593Smuzhiyun static int cs_etm__process_event(struct perf_session *session,
2336*4882a593Smuzhiyun 				 union perf_event *event,
2337*4882a593Smuzhiyun 				 struct perf_sample *sample,
2338*4882a593Smuzhiyun 				 struct perf_tool *tool)
2339*4882a593Smuzhiyun {
2340*4882a593Smuzhiyun 	int err = 0;
2341*4882a593Smuzhiyun 	u64 timestamp;
2342*4882a593Smuzhiyun 	struct cs_etm_auxtrace *etm = container_of(session->auxtrace,
2343*4882a593Smuzhiyun 						   struct cs_etm_auxtrace,
2344*4882a593Smuzhiyun 						   auxtrace);
2345*4882a593Smuzhiyun 
2346*4882a593Smuzhiyun 	if (dump_trace)
2347*4882a593Smuzhiyun 		return 0;
2348*4882a593Smuzhiyun 
2349*4882a593Smuzhiyun 	if (!tool->ordered_events) {
2350*4882a593Smuzhiyun 		pr_err("CoreSight ETM Trace requires ordered events\n");
2351*4882a593Smuzhiyun 		return -EINVAL;
2352*4882a593Smuzhiyun 	}
2353*4882a593Smuzhiyun 
2354*4882a593Smuzhiyun 	if (sample->time && (sample->time != (u64) -1))
2355*4882a593Smuzhiyun 		timestamp = sample->time;
2356*4882a593Smuzhiyun 	else
2357*4882a593Smuzhiyun 		timestamp = 0;
2358*4882a593Smuzhiyun 
2359*4882a593Smuzhiyun 	if (timestamp || etm->timeless_decoding) {
2360*4882a593Smuzhiyun 		err = cs_etm__update_queues(etm);
2361*4882a593Smuzhiyun 		if (err)
2362*4882a593Smuzhiyun 			return err;
2363*4882a593Smuzhiyun 	}
2364*4882a593Smuzhiyun 
2365*4882a593Smuzhiyun 	if (etm->timeless_decoding &&
2366*4882a593Smuzhiyun 	    event->header.type == PERF_RECORD_EXIT)
2367*4882a593Smuzhiyun 		return cs_etm__process_timeless_queues(etm,
2368*4882a593Smuzhiyun 						       event->fork.tid);
2369*4882a593Smuzhiyun 
2370*4882a593Smuzhiyun 	if (event->header.type == PERF_RECORD_ITRACE_START)
2371*4882a593Smuzhiyun 		return cs_etm__process_itrace_start(etm, event);
2372*4882a593Smuzhiyun 	else if (event->header.type == PERF_RECORD_SWITCH_CPU_WIDE)
2373*4882a593Smuzhiyun 		return cs_etm__process_switch_cpu_wide(etm, event);
2374*4882a593Smuzhiyun 
2375*4882a593Smuzhiyun 	if (!etm->timeless_decoding &&
2376*4882a593Smuzhiyun 	    event->header.type == PERF_RECORD_AUX)
2377*4882a593Smuzhiyun 		return cs_etm__process_queues(etm);
2378*4882a593Smuzhiyun 
2379*4882a593Smuzhiyun 	return 0;
2380*4882a593Smuzhiyun }
2381*4882a593Smuzhiyun 
cs_etm__process_auxtrace_event(struct perf_session * session,union perf_event * event,struct perf_tool * tool __maybe_unused)2382*4882a593Smuzhiyun static int cs_etm__process_auxtrace_event(struct perf_session *session,
2383*4882a593Smuzhiyun 					  union perf_event *event,
2384*4882a593Smuzhiyun 					  struct perf_tool *tool __maybe_unused)
2385*4882a593Smuzhiyun {
2386*4882a593Smuzhiyun 	struct cs_etm_auxtrace *etm = container_of(session->auxtrace,
2387*4882a593Smuzhiyun 						   struct cs_etm_auxtrace,
2388*4882a593Smuzhiyun 						   auxtrace);
2389*4882a593Smuzhiyun 	if (!etm->data_queued) {
2390*4882a593Smuzhiyun 		struct auxtrace_buffer *buffer;
2391*4882a593Smuzhiyun 		off_t  data_offset;
2392*4882a593Smuzhiyun 		int fd = perf_data__fd(session->data);
2393*4882a593Smuzhiyun 		bool is_pipe = perf_data__is_pipe(session->data);
2394*4882a593Smuzhiyun 		int err;
2395*4882a593Smuzhiyun 
2396*4882a593Smuzhiyun 		if (is_pipe)
2397*4882a593Smuzhiyun 			data_offset = 0;
2398*4882a593Smuzhiyun 		else {
2399*4882a593Smuzhiyun 			data_offset = lseek(fd, 0, SEEK_CUR);
2400*4882a593Smuzhiyun 			if (data_offset == -1)
2401*4882a593Smuzhiyun 				return -errno;
2402*4882a593Smuzhiyun 		}
2403*4882a593Smuzhiyun 
2404*4882a593Smuzhiyun 		err = auxtrace_queues__add_event(&etm->queues, session,
2405*4882a593Smuzhiyun 						 event, data_offset, &buffer);
2406*4882a593Smuzhiyun 		if (err)
2407*4882a593Smuzhiyun 			return err;
2408*4882a593Smuzhiyun 
2409*4882a593Smuzhiyun 		if (dump_trace)
2410*4882a593Smuzhiyun 			if (auxtrace_buffer__get_data(buffer, fd)) {
2411*4882a593Smuzhiyun 				cs_etm__dump_event(etm, buffer);
2412*4882a593Smuzhiyun 				auxtrace_buffer__put_data(buffer);
2413*4882a593Smuzhiyun 			}
2414*4882a593Smuzhiyun 	}
2415*4882a593Smuzhiyun 
2416*4882a593Smuzhiyun 	return 0;
2417*4882a593Smuzhiyun }
2418*4882a593Smuzhiyun 
cs_etm__is_timeless_decoding(struct cs_etm_auxtrace * etm)2419*4882a593Smuzhiyun static bool cs_etm__is_timeless_decoding(struct cs_etm_auxtrace *etm)
2420*4882a593Smuzhiyun {
2421*4882a593Smuzhiyun 	struct evsel *evsel;
2422*4882a593Smuzhiyun 	struct evlist *evlist = etm->session->evlist;
2423*4882a593Smuzhiyun 	bool timeless_decoding = true;
2424*4882a593Smuzhiyun 
2425*4882a593Smuzhiyun 	/*
2426*4882a593Smuzhiyun 	 * Circle through the list of event and complain if we find one
2427*4882a593Smuzhiyun 	 * with the time bit set.
2428*4882a593Smuzhiyun 	 */
2429*4882a593Smuzhiyun 	evlist__for_each_entry(evlist, evsel) {
2430*4882a593Smuzhiyun 		if ((evsel->core.attr.sample_type & PERF_SAMPLE_TIME))
2431*4882a593Smuzhiyun 			timeless_decoding = false;
2432*4882a593Smuzhiyun 	}
2433*4882a593Smuzhiyun 
2434*4882a593Smuzhiyun 	return timeless_decoding;
2435*4882a593Smuzhiyun }
2436*4882a593Smuzhiyun 
2437*4882a593Smuzhiyun static const char * const cs_etm_global_header_fmts[] = {
2438*4882a593Smuzhiyun 	[CS_HEADER_VERSION_0]	= "	Header version		       %llx\n",
2439*4882a593Smuzhiyun 	[CS_PMU_TYPE_CPUS]	= "	PMU type/num cpus	       %llx\n",
2440*4882a593Smuzhiyun 	[CS_ETM_SNAPSHOT]	= "	Snapshot		       %llx\n",
2441*4882a593Smuzhiyun };
2442*4882a593Smuzhiyun 
2443*4882a593Smuzhiyun static const char * const cs_etm_priv_fmts[] = {
2444*4882a593Smuzhiyun 	[CS_ETM_MAGIC]		= "	Magic number		       %llx\n",
2445*4882a593Smuzhiyun 	[CS_ETM_CPU]		= "	CPU			       %lld\n",
2446*4882a593Smuzhiyun 	[CS_ETM_ETMCR]		= "	ETMCR			       %llx\n",
2447*4882a593Smuzhiyun 	[CS_ETM_ETMTRACEIDR]	= "	ETMTRACEIDR		       %llx\n",
2448*4882a593Smuzhiyun 	[CS_ETM_ETMCCER]	= "	ETMCCER			       %llx\n",
2449*4882a593Smuzhiyun 	[CS_ETM_ETMIDR]		= "	ETMIDR			       %llx\n",
2450*4882a593Smuzhiyun };
2451*4882a593Smuzhiyun 
2452*4882a593Smuzhiyun static const char * const cs_etmv4_priv_fmts[] = {
2453*4882a593Smuzhiyun 	[CS_ETM_MAGIC]		= "	Magic number		       %llx\n",
2454*4882a593Smuzhiyun 	[CS_ETM_CPU]		= "	CPU			       %lld\n",
2455*4882a593Smuzhiyun 	[CS_ETMV4_TRCCONFIGR]	= "	TRCCONFIGR		       %llx\n",
2456*4882a593Smuzhiyun 	[CS_ETMV4_TRCTRACEIDR]	= "	TRCTRACEIDR		       %llx\n",
2457*4882a593Smuzhiyun 	[CS_ETMV4_TRCIDR0]	= "	TRCIDR0			       %llx\n",
2458*4882a593Smuzhiyun 	[CS_ETMV4_TRCIDR1]	= "	TRCIDR1			       %llx\n",
2459*4882a593Smuzhiyun 	[CS_ETMV4_TRCIDR2]	= "	TRCIDR2			       %llx\n",
2460*4882a593Smuzhiyun 	[CS_ETMV4_TRCIDR8]	= "	TRCIDR8			       %llx\n",
2461*4882a593Smuzhiyun 	[CS_ETMV4_TRCAUTHSTATUS] = "	TRCAUTHSTATUS		       %llx\n",
2462*4882a593Smuzhiyun };
2463*4882a593Smuzhiyun 
cs_etm__print_auxtrace_info(__u64 * val,int num)2464*4882a593Smuzhiyun static void cs_etm__print_auxtrace_info(__u64 *val, int num)
2465*4882a593Smuzhiyun {
2466*4882a593Smuzhiyun 	int i, j, cpu = 0;
2467*4882a593Smuzhiyun 
2468*4882a593Smuzhiyun 	for (i = 0; i < CS_HEADER_VERSION_0_MAX; i++)
2469*4882a593Smuzhiyun 		fprintf(stdout, cs_etm_global_header_fmts[i], val[i]);
2470*4882a593Smuzhiyun 
2471*4882a593Smuzhiyun 	for (i = CS_HEADER_VERSION_0_MAX; cpu < num; cpu++) {
2472*4882a593Smuzhiyun 		if (val[i] == __perf_cs_etmv3_magic)
2473*4882a593Smuzhiyun 			for (j = 0; j < CS_ETM_PRIV_MAX; j++, i++)
2474*4882a593Smuzhiyun 				fprintf(stdout, cs_etm_priv_fmts[j], val[i]);
2475*4882a593Smuzhiyun 		else if (val[i] == __perf_cs_etmv4_magic)
2476*4882a593Smuzhiyun 			for (j = 0; j < CS_ETMV4_PRIV_MAX; j++, i++)
2477*4882a593Smuzhiyun 				fprintf(stdout, cs_etmv4_priv_fmts[j], val[i]);
2478*4882a593Smuzhiyun 		else
2479*4882a593Smuzhiyun 			/* failure.. return */
2480*4882a593Smuzhiyun 			return;
2481*4882a593Smuzhiyun 	}
2482*4882a593Smuzhiyun }
2483*4882a593Smuzhiyun 
cs_etm__process_auxtrace_info(union perf_event * event,struct perf_session * session)2484*4882a593Smuzhiyun int cs_etm__process_auxtrace_info(union perf_event *event,
2485*4882a593Smuzhiyun 				  struct perf_session *session)
2486*4882a593Smuzhiyun {
2487*4882a593Smuzhiyun 	struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info;
2488*4882a593Smuzhiyun 	struct cs_etm_auxtrace *etm = NULL;
2489*4882a593Smuzhiyun 	struct int_node *inode;
2490*4882a593Smuzhiyun 	unsigned int pmu_type;
2491*4882a593Smuzhiyun 	int event_header_size = sizeof(struct perf_event_header);
2492*4882a593Smuzhiyun 	int info_header_size;
2493*4882a593Smuzhiyun 	int total_size = auxtrace_info->header.size;
2494*4882a593Smuzhiyun 	int priv_size = 0;
2495*4882a593Smuzhiyun 	int num_cpu;
2496*4882a593Smuzhiyun 	int err = 0, idx = -1;
2497*4882a593Smuzhiyun 	int i, j, k;
2498*4882a593Smuzhiyun 	u64 *ptr, *hdr = NULL;
2499*4882a593Smuzhiyun 	u64 **metadata = NULL;
2500*4882a593Smuzhiyun 
2501*4882a593Smuzhiyun 	/*
2502*4882a593Smuzhiyun 	 * sizeof(auxtrace_info_event::type) +
2503*4882a593Smuzhiyun 	 * sizeof(auxtrace_info_event::reserved) == 8
2504*4882a593Smuzhiyun 	 */
2505*4882a593Smuzhiyun 	info_header_size = 8;
2506*4882a593Smuzhiyun 
2507*4882a593Smuzhiyun 	if (total_size < (event_header_size + info_header_size))
2508*4882a593Smuzhiyun 		return -EINVAL;
2509*4882a593Smuzhiyun 
2510*4882a593Smuzhiyun 	priv_size = total_size - event_header_size - info_header_size;
2511*4882a593Smuzhiyun 
2512*4882a593Smuzhiyun 	/* First the global part */
2513*4882a593Smuzhiyun 	ptr = (u64 *) auxtrace_info->priv;
2514*4882a593Smuzhiyun 
2515*4882a593Smuzhiyun 	/* Look for version '0' of the header */
2516*4882a593Smuzhiyun 	if (ptr[0] != 0)
2517*4882a593Smuzhiyun 		return -EINVAL;
2518*4882a593Smuzhiyun 
2519*4882a593Smuzhiyun 	hdr = zalloc(sizeof(*hdr) * CS_HEADER_VERSION_0_MAX);
2520*4882a593Smuzhiyun 	if (!hdr)
2521*4882a593Smuzhiyun 		return -ENOMEM;
2522*4882a593Smuzhiyun 
2523*4882a593Smuzhiyun 	/* Extract header information - see cs-etm.h for format */
2524*4882a593Smuzhiyun 	for (i = 0; i < CS_HEADER_VERSION_0_MAX; i++)
2525*4882a593Smuzhiyun 		hdr[i] = ptr[i];
2526*4882a593Smuzhiyun 	num_cpu = hdr[CS_PMU_TYPE_CPUS] & 0xffffffff;
2527*4882a593Smuzhiyun 	pmu_type = (unsigned int) ((hdr[CS_PMU_TYPE_CPUS] >> 32) &
2528*4882a593Smuzhiyun 				    0xffffffff);
2529*4882a593Smuzhiyun 
2530*4882a593Smuzhiyun 	/*
2531*4882a593Smuzhiyun 	 * Create an RB tree for traceID-metadata tuple.  Since the conversion
2532*4882a593Smuzhiyun 	 * has to be made for each packet that gets decoded, optimizing access
2533*4882a593Smuzhiyun 	 * in anything other than a sequential array is worth doing.
2534*4882a593Smuzhiyun 	 */
2535*4882a593Smuzhiyun 	traceid_list = intlist__new(NULL);
2536*4882a593Smuzhiyun 	if (!traceid_list) {
2537*4882a593Smuzhiyun 		err = -ENOMEM;
2538*4882a593Smuzhiyun 		goto err_free_hdr;
2539*4882a593Smuzhiyun 	}
2540*4882a593Smuzhiyun 
2541*4882a593Smuzhiyun 	metadata = zalloc(sizeof(*metadata) * num_cpu);
2542*4882a593Smuzhiyun 	if (!metadata) {
2543*4882a593Smuzhiyun 		err = -ENOMEM;
2544*4882a593Smuzhiyun 		goto err_free_traceid_list;
2545*4882a593Smuzhiyun 	}
2546*4882a593Smuzhiyun 
2547*4882a593Smuzhiyun 	/*
2548*4882a593Smuzhiyun 	 * The metadata is stored in the auxtrace_info section and encodes
2549*4882a593Smuzhiyun 	 * the configuration of the ARM embedded trace macrocell which is
2550*4882a593Smuzhiyun 	 * required by the trace decoder to properly decode the trace due
2551*4882a593Smuzhiyun 	 * to its highly compressed nature.
2552*4882a593Smuzhiyun 	 */
2553*4882a593Smuzhiyun 	for (j = 0; j < num_cpu; j++) {
2554*4882a593Smuzhiyun 		if (ptr[i] == __perf_cs_etmv3_magic) {
2555*4882a593Smuzhiyun 			metadata[j] = zalloc(sizeof(*metadata[j]) *
2556*4882a593Smuzhiyun 					     CS_ETM_PRIV_MAX);
2557*4882a593Smuzhiyun 			if (!metadata[j]) {
2558*4882a593Smuzhiyun 				err = -ENOMEM;
2559*4882a593Smuzhiyun 				goto err_free_metadata;
2560*4882a593Smuzhiyun 			}
2561*4882a593Smuzhiyun 			for (k = 0; k < CS_ETM_PRIV_MAX; k++)
2562*4882a593Smuzhiyun 				metadata[j][k] = ptr[i + k];
2563*4882a593Smuzhiyun 
2564*4882a593Smuzhiyun 			/* The traceID is our handle */
2565*4882a593Smuzhiyun 			idx = metadata[j][CS_ETM_ETMTRACEIDR];
2566*4882a593Smuzhiyun 			i += CS_ETM_PRIV_MAX;
2567*4882a593Smuzhiyun 		} else if (ptr[i] == __perf_cs_etmv4_magic) {
2568*4882a593Smuzhiyun 			metadata[j] = zalloc(sizeof(*metadata[j]) *
2569*4882a593Smuzhiyun 					     CS_ETMV4_PRIV_MAX);
2570*4882a593Smuzhiyun 			if (!metadata[j]) {
2571*4882a593Smuzhiyun 				err = -ENOMEM;
2572*4882a593Smuzhiyun 				goto err_free_metadata;
2573*4882a593Smuzhiyun 			}
2574*4882a593Smuzhiyun 			for (k = 0; k < CS_ETMV4_PRIV_MAX; k++)
2575*4882a593Smuzhiyun 				metadata[j][k] = ptr[i + k];
2576*4882a593Smuzhiyun 
2577*4882a593Smuzhiyun 			/* The traceID is our handle */
2578*4882a593Smuzhiyun 			idx = metadata[j][CS_ETMV4_TRCTRACEIDR];
2579*4882a593Smuzhiyun 			i += CS_ETMV4_PRIV_MAX;
2580*4882a593Smuzhiyun 		}
2581*4882a593Smuzhiyun 
2582*4882a593Smuzhiyun 		/* Get an RB node for this CPU */
2583*4882a593Smuzhiyun 		inode = intlist__findnew(traceid_list, idx);
2584*4882a593Smuzhiyun 
2585*4882a593Smuzhiyun 		/* Something went wrong, no need to continue */
2586*4882a593Smuzhiyun 		if (!inode) {
2587*4882a593Smuzhiyun 			err = -ENOMEM;
2588*4882a593Smuzhiyun 			goto err_free_metadata;
2589*4882a593Smuzhiyun 		}
2590*4882a593Smuzhiyun 
2591*4882a593Smuzhiyun 		/*
2592*4882a593Smuzhiyun 		 * The node for that CPU should not be taken.
2593*4882a593Smuzhiyun 		 * Back out if that's the case.
2594*4882a593Smuzhiyun 		 */
2595*4882a593Smuzhiyun 		if (inode->priv) {
2596*4882a593Smuzhiyun 			err = -EINVAL;
2597*4882a593Smuzhiyun 			goto err_free_metadata;
2598*4882a593Smuzhiyun 		}
2599*4882a593Smuzhiyun 		/* All good, associate the traceID with the metadata pointer */
2600*4882a593Smuzhiyun 		inode->priv = metadata[j];
2601*4882a593Smuzhiyun 	}
2602*4882a593Smuzhiyun 
2603*4882a593Smuzhiyun 	/*
2604*4882a593Smuzhiyun 	 * Each of CS_HEADER_VERSION_0_MAX, CS_ETM_PRIV_MAX and
2605*4882a593Smuzhiyun 	 * CS_ETMV4_PRIV_MAX mark how many double words are in the
2606*4882a593Smuzhiyun 	 * global metadata, and each cpu's metadata respectively.
2607*4882a593Smuzhiyun 	 * The following tests if the correct number of double words was
2608*4882a593Smuzhiyun 	 * present in the auxtrace info section.
2609*4882a593Smuzhiyun 	 */
2610*4882a593Smuzhiyun 	if (i * 8 != priv_size) {
2611*4882a593Smuzhiyun 		err = -EINVAL;
2612*4882a593Smuzhiyun 		goto err_free_metadata;
2613*4882a593Smuzhiyun 	}
2614*4882a593Smuzhiyun 
2615*4882a593Smuzhiyun 	etm = zalloc(sizeof(*etm));
2616*4882a593Smuzhiyun 
2617*4882a593Smuzhiyun 	if (!etm) {
2618*4882a593Smuzhiyun 		err = -ENOMEM;
2619*4882a593Smuzhiyun 		goto err_free_metadata;
2620*4882a593Smuzhiyun 	}
2621*4882a593Smuzhiyun 
2622*4882a593Smuzhiyun 	err = auxtrace_queues__init(&etm->queues);
2623*4882a593Smuzhiyun 	if (err)
2624*4882a593Smuzhiyun 		goto err_free_etm;
2625*4882a593Smuzhiyun 
2626*4882a593Smuzhiyun 	etm->session = session;
2627*4882a593Smuzhiyun 	etm->machine = &session->machines.host;
2628*4882a593Smuzhiyun 
2629*4882a593Smuzhiyun 	etm->num_cpu = num_cpu;
2630*4882a593Smuzhiyun 	etm->pmu_type = pmu_type;
2631*4882a593Smuzhiyun 	etm->snapshot_mode = (hdr[CS_ETM_SNAPSHOT] != 0);
2632*4882a593Smuzhiyun 	etm->metadata = metadata;
2633*4882a593Smuzhiyun 	etm->auxtrace_type = auxtrace_info->type;
2634*4882a593Smuzhiyun 	etm->timeless_decoding = cs_etm__is_timeless_decoding(etm);
2635*4882a593Smuzhiyun 
2636*4882a593Smuzhiyun 	etm->auxtrace.process_event = cs_etm__process_event;
2637*4882a593Smuzhiyun 	etm->auxtrace.process_auxtrace_event = cs_etm__process_auxtrace_event;
2638*4882a593Smuzhiyun 	etm->auxtrace.flush_events = cs_etm__flush_events;
2639*4882a593Smuzhiyun 	etm->auxtrace.free_events = cs_etm__free_events;
2640*4882a593Smuzhiyun 	etm->auxtrace.free = cs_etm__free;
2641*4882a593Smuzhiyun 	etm->auxtrace.evsel_is_auxtrace = cs_etm__evsel_is_auxtrace;
2642*4882a593Smuzhiyun 	session->auxtrace = &etm->auxtrace;
2643*4882a593Smuzhiyun 
2644*4882a593Smuzhiyun 	etm->unknown_thread = thread__new(999999999, 999999999);
2645*4882a593Smuzhiyun 	if (!etm->unknown_thread) {
2646*4882a593Smuzhiyun 		err = -ENOMEM;
2647*4882a593Smuzhiyun 		goto err_free_queues;
2648*4882a593Smuzhiyun 	}
2649*4882a593Smuzhiyun 
2650*4882a593Smuzhiyun 	/*
2651*4882a593Smuzhiyun 	 * Initialize list node so that at thread__zput() we can avoid
2652*4882a593Smuzhiyun 	 * segmentation fault at list_del_init().
2653*4882a593Smuzhiyun 	 */
2654*4882a593Smuzhiyun 	INIT_LIST_HEAD(&etm->unknown_thread->node);
2655*4882a593Smuzhiyun 
2656*4882a593Smuzhiyun 	err = thread__set_comm(etm->unknown_thread, "unknown", 0);
2657*4882a593Smuzhiyun 	if (err)
2658*4882a593Smuzhiyun 		goto err_delete_thread;
2659*4882a593Smuzhiyun 
2660*4882a593Smuzhiyun 	if (thread__init_maps(etm->unknown_thread, etm->machine)) {
2661*4882a593Smuzhiyun 		err = -ENOMEM;
2662*4882a593Smuzhiyun 		goto err_delete_thread;
2663*4882a593Smuzhiyun 	}
2664*4882a593Smuzhiyun 
2665*4882a593Smuzhiyun 	if (dump_trace) {
2666*4882a593Smuzhiyun 		cs_etm__print_auxtrace_info(auxtrace_info->priv, num_cpu);
2667*4882a593Smuzhiyun 		return 0;
2668*4882a593Smuzhiyun 	}
2669*4882a593Smuzhiyun 
2670*4882a593Smuzhiyun 	if (session->itrace_synth_opts->set) {
2671*4882a593Smuzhiyun 		etm->synth_opts = *session->itrace_synth_opts;
2672*4882a593Smuzhiyun 	} else {
2673*4882a593Smuzhiyun 		itrace_synth_opts__set_default(&etm->synth_opts,
2674*4882a593Smuzhiyun 				session->itrace_synth_opts->default_no_sample);
2675*4882a593Smuzhiyun 		etm->synth_opts.callchain = false;
2676*4882a593Smuzhiyun 	}
2677*4882a593Smuzhiyun 
2678*4882a593Smuzhiyun 	err = cs_etm__synth_events(etm, session);
2679*4882a593Smuzhiyun 	if (err)
2680*4882a593Smuzhiyun 		goto err_delete_thread;
2681*4882a593Smuzhiyun 
2682*4882a593Smuzhiyun 	err = auxtrace_queues__process_index(&etm->queues, session);
2683*4882a593Smuzhiyun 	if (err)
2684*4882a593Smuzhiyun 		goto err_delete_thread;
2685*4882a593Smuzhiyun 
2686*4882a593Smuzhiyun 	etm->data_queued = etm->queues.populated;
2687*4882a593Smuzhiyun 
2688*4882a593Smuzhiyun 	return 0;
2689*4882a593Smuzhiyun 
2690*4882a593Smuzhiyun err_delete_thread:
2691*4882a593Smuzhiyun 	thread__zput(etm->unknown_thread);
2692*4882a593Smuzhiyun err_free_queues:
2693*4882a593Smuzhiyun 	auxtrace_queues__free(&etm->queues);
2694*4882a593Smuzhiyun 	session->auxtrace = NULL;
2695*4882a593Smuzhiyun err_free_etm:
2696*4882a593Smuzhiyun 	zfree(&etm);
2697*4882a593Smuzhiyun err_free_metadata:
2698*4882a593Smuzhiyun 	/* No need to check @metadata[j], free(NULL) is supported */
2699*4882a593Smuzhiyun 	for (j = 0; j < num_cpu; j++)
2700*4882a593Smuzhiyun 		zfree(&metadata[j]);
2701*4882a593Smuzhiyun 	zfree(&metadata);
2702*4882a593Smuzhiyun err_free_traceid_list:
2703*4882a593Smuzhiyun 	intlist__delete(traceid_list);
2704*4882a593Smuzhiyun err_free_hdr:
2705*4882a593Smuzhiyun 	zfree(&hdr);
2706*4882a593Smuzhiyun 
2707*4882a593Smuzhiyun 	return err;
2708*4882a593Smuzhiyun }
2709