xref: /OK3568_Linux_fs/kernel/tools/perf/util/cs-etm.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright(C) 2015 Linaro Limited. All rights reserved.
4*4882a593Smuzhiyun  * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #ifndef INCLUDE__UTIL_PERF_CS_ETM_H__
8*4882a593Smuzhiyun #define INCLUDE__UTIL_PERF_CS_ETM_H__
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include "util/event.h"
11*4882a593Smuzhiyun #include <linux/bits.h>
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun struct perf_session;
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun /* Versionning header in case things need tro change in the future.  That way
16*4882a593Smuzhiyun  * decoding of old snapshot is still possible.
17*4882a593Smuzhiyun  */
18*4882a593Smuzhiyun enum {
19*4882a593Smuzhiyun 	/* Starting with 0x0 */
20*4882a593Smuzhiyun 	CS_HEADER_VERSION_0,
21*4882a593Smuzhiyun 	/* PMU->type (32 bit), total # of CPUs (32 bit) */
22*4882a593Smuzhiyun 	CS_PMU_TYPE_CPUS,
23*4882a593Smuzhiyun 	CS_ETM_SNAPSHOT,
24*4882a593Smuzhiyun 	CS_HEADER_VERSION_0_MAX,
25*4882a593Smuzhiyun };
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun /* Beginning of header common to both ETMv3 and V4 */
28*4882a593Smuzhiyun enum {
29*4882a593Smuzhiyun 	CS_ETM_MAGIC,
30*4882a593Smuzhiyun 	CS_ETM_CPU,
31*4882a593Smuzhiyun };
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun /* ETMv3/PTM metadata */
34*4882a593Smuzhiyun enum {
35*4882a593Smuzhiyun 	/* Dynamic, configurable parameters */
36*4882a593Smuzhiyun 	CS_ETM_ETMCR = CS_ETM_CPU + 1,
37*4882a593Smuzhiyun 	CS_ETM_ETMTRACEIDR,
38*4882a593Smuzhiyun 	/* RO, taken from sysFS */
39*4882a593Smuzhiyun 	CS_ETM_ETMCCER,
40*4882a593Smuzhiyun 	CS_ETM_ETMIDR,
41*4882a593Smuzhiyun 	CS_ETM_PRIV_MAX,
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun /* ETMv4 metadata */
45*4882a593Smuzhiyun enum {
46*4882a593Smuzhiyun 	/* Dynamic, configurable parameters */
47*4882a593Smuzhiyun 	CS_ETMV4_TRCCONFIGR = CS_ETM_CPU + 1,
48*4882a593Smuzhiyun 	CS_ETMV4_TRCTRACEIDR,
49*4882a593Smuzhiyun 	/* RO, taken from sysFS */
50*4882a593Smuzhiyun 	CS_ETMV4_TRCIDR0,
51*4882a593Smuzhiyun 	CS_ETMV4_TRCIDR1,
52*4882a593Smuzhiyun 	CS_ETMV4_TRCIDR2,
53*4882a593Smuzhiyun 	CS_ETMV4_TRCIDR8,
54*4882a593Smuzhiyun 	CS_ETMV4_TRCAUTHSTATUS,
55*4882a593Smuzhiyun 	CS_ETMV4_PRIV_MAX,
56*4882a593Smuzhiyun };
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun /*
59*4882a593Smuzhiyun  * ETMv3 exception encoding number:
60*4882a593Smuzhiyun  * See Embedded Trace Macrocell spcification (ARM IHI 0014Q)
61*4882a593Smuzhiyun  * table 7-12 Encoding of Exception[3:0] for non-ARMv7-M processors.
62*4882a593Smuzhiyun  */
63*4882a593Smuzhiyun enum {
64*4882a593Smuzhiyun 	CS_ETMV3_EXC_NONE = 0,
65*4882a593Smuzhiyun 	CS_ETMV3_EXC_DEBUG_HALT = 1,
66*4882a593Smuzhiyun 	CS_ETMV3_EXC_SMC = 2,
67*4882a593Smuzhiyun 	CS_ETMV3_EXC_HYP = 3,
68*4882a593Smuzhiyun 	CS_ETMV3_EXC_ASYNC_DATA_ABORT = 4,
69*4882a593Smuzhiyun 	CS_ETMV3_EXC_JAZELLE_THUMBEE = 5,
70*4882a593Smuzhiyun 	CS_ETMV3_EXC_PE_RESET = 8,
71*4882a593Smuzhiyun 	CS_ETMV3_EXC_UNDEFINED_INSTR = 9,
72*4882a593Smuzhiyun 	CS_ETMV3_EXC_SVC = 10,
73*4882a593Smuzhiyun 	CS_ETMV3_EXC_PREFETCH_ABORT = 11,
74*4882a593Smuzhiyun 	CS_ETMV3_EXC_DATA_FAULT = 12,
75*4882a593Smuzhiyun 	CS_ETMV3_EXC_GENERIC = 13,
76*4882a593Smuzhiyun 	CS_ETMV3_EXC_IRQ = 14,
77*4882a593Smuzhiyun 	CS_ETMV3_EXC_FIQ = 15,
78*4882a593Smuzhiyun };
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun /*
81*4882a593Smuzhiyun  * ETMv4 exception encoding number:
82*4882a593Smuzhiyun  * See ARM Embedded Trace Macrocell Architecture Specification (ARM IHI 0064D)
83*4882a593Smuzhiyun  * table 6-12 Possible values for the TYPE field in an Exception instruction
84*4882a593Smuzhiyun  * trace packet, for ARMv7-A/R and ARMv8-A/R PEs.
85*4882a593Smuzhiyun  */
86*4882a593Smuzhiyun enum {
87*4882a593Smuzhiyun 	CS_ETMV4_EXC_RESET = 0,
88*4882a593Smuzhiyun 	CS_ETMV4_EXC_DEBUG_HALT = 1,
89*4882a593Smuzhiyun 	CS_ETMV4_EXC_CALL = 2,
90*4882a593Smuzhiyun 	CS_ETMV4_EXC_TRAP = 3,
91*4882a593Smuzhiyun 	CS_ETMV4_EXC_SYSTEM_ERROR = 4,
92*4882a593Smuzhiyun 	CS_ETMV4_EXC_INST_DEBUG = 6,
93*4882a593Smuzhiyun 	CS_ETMV4_EXC_DATA_DEBUG = 7,
94*4882a593Smuzhiyun 	CS_ETMV4_EXC_ALIGNMENT = 10,
95*4882a593Smuzhiyun 	CS_ETMV4_EXC_INST_FAULT = 11,
96*4882a593Smuzhiyun 	CS_ETMV4_EXC_DATA_FAULT = 12,
97*4882a593Smuzhiyun 	CS_ETMV4_EXC_IRQ = 14,
98*4882a593Smuzhiyun 	CS_ETMV4_EXC_FIQ = 15,
99*4882a593Smuzhiyun 	CS_ETMV4_EXC_END = 31,
100*4882a593Smuzhiyun };
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun enum cs_etm_sample_type {
103*4882a593Smuzhiyun 	CS_ETM_EMPTY,
104*4882a593Smuzhiyun 	CS_ETM_RANGE,
105*4882a593Smuzhiyun 	CS_ETM_DISCONTINUITY,
106*4882a593Smuzhiyun 	CS_ETM_EXCEPTION,
107*4882a593Smuzhiyun 	CS_ETM_EXCEPTION_RET,
108*4882a593Smuzhiyun };
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun enum cs_etm_isa {
111*4882a593Smuzhiyun 	CS_ETM_ISA_UNKNOWN,
112*4882a593Smuzhiyun 	CS_ETM_ISA_A64,
113*4882a593Smuzhiyun 	CS_ETM_ISA_A32,
114*4882a593Smuzhiyun 	CS_ETM_ISA_T32,
115*4882a593Smuzhiyun };
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun struct cs_etm_queue;
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun struct cs_etm_packet {
120*4882a593Smuzhiyun 	enum cs_etm_sample_type sample_type;
121*4882a593Smuzhiyun 	enum cs_etm_isa isa;
122*4882a593Smuzhiyun 	u64 start_addr;
123*4882a593Smuzhiyun 	u64 end_addr;
124*4882a593Smuzhiyun 	u32 instr_count;
125*4882a593Smuzhiyun 	u32 last_instr_type;
126*4882a593Smuzhiyun 	u32 last_instr_subtype;
127*4882a593Smuzhiyun 	u32 flags;
128*4882a593Smuzhiyun 	u32 exception_number;
129*4882a593Smuzhiyun 	u8 last_instr_cond;
130*4882a593Smuzhiyun 	u8 last_instr_taken_branch;
131*4882a593Smuzhiyun 	u8 last_instr_size;
132*4882a593Smuzhiyun 	u8 trace_chan_id;
133*4882a593Smuzhiyun 	int cpu;
134*4882a593Smuzhiyun };
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun #define CS_ETM_PACKET_MAX_BUFFER 1024
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun /*
139*4882a593Smuzhiyun  * When working with per-thread scenarios the process under trace can
140*4882a593Smuzhiyun  * be scheduled on any CPU and as such, more than one traceID may be
141*4882a593Smuzhiyun  * associated with the same process.  Since a traceID of '0' is illegal
142*4882a593Smuzhiyun  * as per the CoreSight architecture, use that specific value to
143*4882a593Smuzhiyun  * identify the queue where all packets (with any traceID) are
144*4882a593Smuzhiyun  * aggregated.
145*4882a593Smuzhiyun  */
146*4882a593Smuzhiyun #define CS_ETM_PER_THREAD_TRACEID 0
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun struct cs_etm_packet_queue {
149*4882a593Smuzhiyun 	u32 packet_count;
150*4882a593Smuzhiyun 	u32 head;
151*4882a593Smuzhiyun 	u32 tail;
152*4882a593Smuzhiyun 	u32 instr_count;
153*4882a593Smuzhiyun 	u64 timestamp;
154*4882a593Smuzhiyun 	u64 next_timestamp;
155*4882a593Smuzhiyun 	struct cs_etm_packet packet_buffer[CS_ETM_PACKET_MAX_BUFFER];
156*4882a593Smuzhiyun };
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun #define KiB(x) ((x) * 1024)
159*4882a593Smuzhiyun #define MiB(x) ((x) * 1024 * 1024)
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun #define CS_ETM_INVAL_ADDR 0xdeadbeefdeadbeefUL
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun #define BMVAL(val, lsb, msb)	((val & GENMASK(msb, lsb)) >> lsb)
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun #define CS_ETM_HEADER_SIZE (CS_HEADER_VERSION_0_MAX * sizeof(u64))
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun #define __perf_cs_etmv3_magic 0x3030303030303030ULL
168*4882a593Smuzhiyun #define __perf_cs_etmv4_magic 0x4040404040404040ULL
169*4882a593Smuzhiyun #define CS_ETMV3_PRIV_SIZE (CS_ETM_PRIV_MAX * sizeof(u64))
170*4882a593Smuzhiyun #define CS_ETMV4_PRIV_SIZE (CS_ETMV4_PRIV_MAX * sizeof(u64))
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun #ifdef HAVE_CSTRACE_SUPPORT
173*4882a593Smuzhiyun int cs_etm__process_auxtrace_info(union perf_event *event,
174*4882a593Smuzhiyun 				  struct perf_session *session);
175*4882a593Smuzhiyun int cs_etm__get_cpu(u8 trace_chan_id, int *cpu);
176*4882a593Smuzhiyun int cs_etm__etmq_set_tid(struct cs_etm_queue *etmq,
177*4882a593Smuzhiyun 			 pid_t tid, u8 trace_chan_id);
178*4882a593Smuzhiyun bool cs_etm__etmq_is_timeless(struct cs_etm_queue *etmq);
179*4882a593Smuzhiyun void cs_etm__etmq_set_traceid_queue_timestamp(struct cs_etm_queue *etmq,
180*4882a593Smuzhiyun 					      u8 trace_chan_id);
181*4882a593Smuzhiyun struct cs_etm_packet_queue
182*4882a593Smuzhiyun *cs_etm__etmq_get_packet_queue(struct cs_etm_queue *etmq, u8 trace_chan_id);
183*4882a593Smuzhiyun #else
184*4882a593Smuzhiyun static inline int
cs_etm__process_auxtrace_info(union perf_event * event __maybe_unused,struct perf_session * session __maybe_unused)185*4882a593Smuzhiyun cs_etm__process_auxtrace_info(union perf_event *event __maybe_unused,
186*4882a593Smuzhiyun 			      struct perf_session *session __maybe_unused)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun 	return -1;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun 
cs_etm__get_cpu(u8 trace_chan_id __maybe_unused,int * cpu __maybe_unused)191*4882a593Smuzhiyun static inline int cs_etm__get_cpu(u8 trace_chan_id __maybe_unused,
192*4882a593Smuzhiyun 				  int *cpu __maybe_unused)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun 	return -1;
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun 
cs_etm__etmq_set_tid(struct cs_etm_queue * etmq __maybe_unused,pid_t tid __maybe_unused,u8 trace_chan_id __maybe_unused)197*4882a593Smuzhiyun static inline int cs_etm__etmq_set_tid(
198*4882a593Smuzhiyun 				struct cs_etm_queue *etmq __maybe_unused,
199*4882a593Smuzhiyun 				pid_t tid __maybe_unused,
200*4882a593Smuzhiyun 				u8 trace_chan_id __maybe_unused)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun 	return -1;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun 
cs_etm__etmq_is_timeless(struct cs_etm_queue * etmq __maybe_unused)205*4882a593Smuzhiyun static inline bool cs_etm__etmq_is_timeless(
206*4882a593Smuzhiyun 				struct cs_etm_queue *etmq __maybe_unused)
207*4882a593Smuzhiyun {
208*4882a593Smuzhiyun 	/* What else to return? */
209*4882a593Smuzhiyun 	return true;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun 
cs_etm__etmq_set_traceid_queue_timestamp(struct cs_etm_queue * etmq __maybe_unused,u8 trace_chan_id __maybe_unused)212*4882a593Smuzhiyun static inline void cs_etm__etmq_set_traceid_queue_timestamp(
213*4882a593Smuzhiyun 				struct cs_etm_queue *etmq __maybe_unused,
214*4882a593Smuzhiyun 				u8 trace_chan_id __maybe_unused) {}
215*4882a593Smuzhiyun 
cs_etm__etmq_get_packet_queue(struct cs_etm_queue * etmq __maybe_unused,u8 trace_chan_id __maybe_unused)216*4882a593Smuzhiyun static inline struct cs_etm_packet_queue *cs_etm__etmq_get_packet_queue(
217*4882a593Smuzhiyun 				struct cs_etm_queue *etmq __maybe_unused,
218*4882a593Smuzhiyun 				u8 trace_chan_id __maybe_unused)
219*4882a593Smuzhiyun {
220*4882a593Smuzhiyun 	return NULL;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun #endif
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun #endif
225