18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright(C) 2015 Linaro Limited. All rights reserved.
48c2ecf20Sopenharmony_ci * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#ifndef INCLUDE__UTIL_PERF_CS_ETM_H__
88c2ecf20Sopenharmony_ci#define INCLUDE__UTIL_PERF_CS_ETM_H__
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include "util/event.h"
118c2ecf20Sopenharmony_ci#include <linux/bits.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_cistruct perf_session;
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci/* Versionning header in case things need tro change in the future.  That way
168c2ecf20Sopenharmony_ci * decoding of old snapshot is still possible.
178c2ecf20Sopenharmony_ci */
188c2ecf20Sopenharmony_cienum {
198c2ecf20Sopenharmony_ci	/* Starting with 0x0 */
208c2ecf20Sopenharmony_ci	CS_HEADER_VERSION_0,
218c2ecf20Sopenharmony_ci	/* PMU->type (32 bit), total # of CPUs (32 bit) */
228c2ecf20Sopenharmony_ci	CS_PMU_TYPE_CPUS,
238c2ecf20Sopenharmony_ci	CS_ETM_SNAPSHOT,
248c2ecf20Sopenharmony_ci	CS_HEADER_VERSION_0_MAX,
258c2ecf20Sopenharmony_ci};
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci/* Beginning of header common to both ETMv3 and V4 */
288c2ecf20Sopenharmony_cienum {
298c2ecf20Sopenharmony_ci	CS_ETM_MAGIC,
308c2ecf20Sopenharmony_ci	CS_ETM_CPU,
318c2ecf20Sopenharmony_ci};
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci/* ETMv3/PTM metadata */
348c2ecf20Sopenharmony_cienum {
358c2ecf20Sopenharmony_ci	/* Dynamic, configurable parameters */
368c2ecf20Sopenharmony_ci	CS_ETM_ETMCR = CS_ETM_CPU + 1,
378c2ecf20Sopenharmony_ci	CS_ETM_ETMTRACEIDR,
388c2ecf20Sopenharmony_ci	/* RO, taken from sysFS */
398c2ecf20Sopenharmony_ci	CS_ETM_ETMCCER,
408c2ecf20Sopenharmony_ci	CS_ETM_ETMIDR,
418c2ecf20Sopenharmony_ci	CS_ETM_PRIV_MAX,
428c2ecf20Sopenharmony_ci};
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci/* ETMv4 metadata */
458c2ecf20Sopenharmony_cienum {
468c2ecf20Sopenharmony_ci	/* Dynamic, configurable parameters */
478c2ecf20Sopenharmony_ci	CS_ETMV4_TRCCONFIGR = CS_ETM_CPU + 1,
488c2ecf20Sopenharmony_ci	CS_ETMV4_TRCTRACEIDR,
498c2ecf20Sopenharmony_ci	/* RO, taken from sysFS */
508c2ecf20Sopenharmony_ci	CS_ETMV4_TRCIDR0,
518c2ecf20Sopenharmony_ci	CS_ETMV4_TRCIDR1,
528c2ecf20Sopenharmony_ci	CS_ETMV4_TRCIDR2,
538c2ecf20Sopenharmony_ci	CS_ETMV4_TRCIDR8,
548c2ecf20Sopenharmony_ci	CS_ETMV4_TRCAUTHSTATUS,
558c2ecf20Sopenharmony_ci	CS_ETMV4_PRIV_MAX,
568c2ecf20Sopenharmony_ci};
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci/*
598c2ecf20Sopenharmony_ci * ETMv3 exception encoding number:
608c2ecf20Sopenharmony_ci * See Embedded Trace Macrocell spcification (ARM IHI 0014Q)
618c2ecf20Sopenharmony_ci * table 7-12 Encoding of Exception[3:0] for non-ARMv7-M processors.
628c2ecf20Sopenharmony_ci */
638c2ecf20Sopenharmony_cienum {
648c2ecf20Sopenharmony_ci	CS_ETMV3_EXC_NONE = 0,
658c2ecf20Sopenharmony_ci	CS_ETMV3_EXC_DEBUG_HALT = 1,
668c2ecf20Sopenharmony_ci	CS_ETMV3_EXC_SMC = 2,
678c2ecf20Sopenharmony_ci	CS_ETMV3_EXC_HYP = 3,
688c2ecf20Sopenharmony_ci	CS_ETMV3_EXC_ASYNC_DATA_ABORT = 4,
698c2ecf20Sopenharmony_ci	CS_ETMV3_EXC_JAZELLE_THUMBEE = 5,
708c2ecf20Sopenharmony_ci	CS_ETMV3_EXC_PE_RESET = 8,
718c2ecf20Sopenharmony_ci	CS_ETMV3_EXC_UNDEFINED_INSTR = 9,
728c2ecf20Sopenharmony_ci	CS_ETMV3_EXC_SVC = 10,
738c2ecf20Sopenharmony_ci	CS_ETMV3_EXC_PREFETCH_ABORT = 11,
748c2ecf20Sopenharmony_ci	CS_ETMV3_EXC_DATA_FAULT = 12,
758c2ecf20Sopenharmony_ci	CS_ETMV3_EXC_GENERIC = 13,
768c2ecf20Sopenharmony_ci	CS_ETMV3_EXC_IRQ = 14,
778c2ecf20Sopenharmony_ci	CS_ETMV3_EXC_FIQ = 15,
788c2ecf20Sopenharmony_ci};
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci/*
818c2ecf20Sopenharmony_ci * ETMv4 exception encoding number:
828c2ecf20Sopenharmony_ci * See ARM Embedded Trace Macrocell Architecture Specification (ARM IHI 0064D)
838c2ecf20Sopenharmony_ci * table 6-12 Possible values for the TYPE field in an Exception instruction
848c2ecf20Sopenharmony_ci * trace packet, for ARMv7-A/R and ARMv8-A/R PEs.
858c2ecf20Sopenharmony_ci */
868c2ecf20Sopenharmony_cienum {
878c2ecf20Sopenharmony_ci	CS_ETMV4_EXC_RESET = 0,
888c2ecf20Sopenharmony_ci	CS_ETMV4_EXC_DEBUG_HALT = 1,
898c2ecf20Sopenharmony_ci	CS_ETMV4_EXC_CALL = 2,
908c2ecf20Sopenharmony_ci	CS_ETMV4_EXC_TRAP = 3,
918c2ecf20Sopenharmony_ci	CS_ETMV4_EXC_SYSTEM_ERROR = 4,
928c2ecf20Sopenharmony_ci	CS_ETMV4_EXC_INST_DEBUG = 6,
938c2ecf20Sopenharmony_ci	CS_ETMV4_EXC_DATA_DEBUG = 7,
948c2ecf20Sopenharmony_ci	CS_ETMV4_EXC_ALIGNMENT = 10,
958c2ecf20Sopenharmony_ci	CS_ETMV4_EXC_INST_FAULT = 11,
968c2ecf20Sopenharmony_ci	CS_ETMV4_EXC_DATA_FAULT = 12,
978c2ecf20Sopenharmony_ci	CS_ETMV4_EXC_IRQ = 14,
988c2ecf20Sopenharmony_ci	CS_ETMV4_EXC_FIQ = 15,
998c2ecf20Sopenharmony_ci	CS_ETMV4_EXC_END = 31,
1008c2ecf20Sopenharmony_ci};
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_cienum cs_etm_sample_type {
1038c2ecf20Sopenharmony_ci	CS_ETM_EMPTY,
1048c2ecf20Sopenharmony_ci	CS_ETM_RANGE,
1058c2ecf20Sopenharmony_ci	CS_ETM_DISCONTINUITY,
1068c2ecf20Sopenharmony_ci	CS_ETM_EXCEPTION,
1078c2ecf20Sopenharmony_ci	CS_ETM_EXCEPTION_RET,
1088c2ecf20Sopenharmony_ci};
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_cienum cs_etm_isa {
1118c2ecf20Sopenharmony_ci	CS_ETM_ISA_UNKNOWN,
1128c2ecf20Sopenharmony_ci	CS_ETM_ISA_A64,
1138c2ecf20Sopenharmony_ci	CS_ETM_ISA_A32,
1148c2ecf20Sopenharmony_ci	CS_ETM_ISA_T32,
1158c2ecf20Sopenharmony_ci};
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_cistruct cs_etm_queue;
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_cistruct cs_etm_packet {
1208c2ecf20Sopenharmony_ci	enum cs_etm_sample_type sample_type;
1218c2ecf20Sopenharmony_ci	enum cs_etm_isa isa;
1228c2ecf20Sopenharmony_ci	u64 start_addr;
1238c2ecf20Sopenharmony_ci	u64 end_addr;
1248c2ecf20Sopenharmony_ci	u32 instr_count;
1258c2ecf20Sopenharmony_ci	u32 last_instr_type;
1268c2ecf20Sopenharmony_ci	u32 last_instr_subtype;
1278c2ecf20Sopenharmony_ci	u32 flags;
1288c2ecf20Sopenharmony_ci	u32 exception_number;
1298c2ecf20Sopenharmony_ci	u8 last_instr_cond;
1308c2ecf20Sopenharmony_ci	u8 last_instr_taken_branch;
1318c2ecf20Sopenharmony_ci	u8 last_instr_size;
1328c2ecf20Sopenharmony_ci	u8 trace_chan_id;
1338c2ecf20Sopenharmony_ci	int cpu;
1348c2ecf20Sopenharmony_ci};
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci#define CS_ETM_PACKET_MAX_BUFFER 1024
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci/*
1398c2ecf20Sopenharmony_ci * When working with per-thread scenarios the process under trace can
1408c2ecf20Sopenharmony_ci * be scheduled on any CPU and as such, more than one traceID may be
1418c2ecf20Sopenharmony_ci * associated with the same process.  Since a traceID of '0' is illegal
1428c2ecf20Sopenharmony_ci * as per the CoreSight architecture, use that specific value to
1438c2ecf20Sopenharmony_ci * identify the queue where all packets (with any traceID) are
1448c2ecf20Sopenharmony_ci * aggregated.
1458c2ecf20Sopenharmony_ci */
1468c2ecf20Sopenharmony_ci#define CS_ETM_PER_THREAD_TRACEID 0
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_cistruct cs_etm_packet_queue {
1498c2ecf20Sopenharmony_ci	u32 packet_count;
1508c2ecf20Sopenharmony_ci	u32 head;
1518c2ecf20Sopenharmony_ci	u32 tail;
1528c2ecf20Sopenharmony_ci	u32 instr_count;
1538c2ecf20Sopenharmony_ci	u64 timestamp;
1548c2ecf20Sopenharmony_ci	u64 next_timestamp;
1558c2ecf20Sopenharmony_ci	struct cs_etm_packet packet_buffer[CS_ETM_PACKET_MAX_BUFFER];
1568c2ecf20Sopenharmony_ci};
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci#define KiB(x) ((x) * 1024)
1598c2ecf20Sopenharmony_ci#define MiB(x) ((x) * 1024 * 1024)
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci#define CS_ETM_INVAL_ADDR 0xdeadbeefdeadbeefUL
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci#define BMVAL(val, lsb, msb)	((val & GENMASK(msb, lsb)) >> lsb)
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci#define CS_ETM_HEADER_SIZE (CS_HEADER_VERSION_0_MAX * sizeof(u64))
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci#define __perf_cs_etmv3_magic 0x3030303030303030ULL
1688c2ecf20Sopenharmony_ci#define __perf_cs_etmv4_magic 0x4040404040404040ULL
1698c2ecf20Sopenharmony_ci#define CS_ETMV3_PRIV_SIZE (CS_ETM_PRIV_MAX * sizeof(u64))
1708c2ecf20Sopenharmony_ci#define CS_ETMV4_PRIV_SIZE (CS_ETMV4_PRIV_MAX * sizeof(u64))
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci#ifdef HAVE_CSTRACE_SUPPORT
1738c2ecf20Sopenharmony_ciint cs_etm__process_auxtrace_info(union perf_event *event,
1748c2ecf20Sopenharmony_ci				  struct perf_session *session);
1758c2ecf20Sopenharmony_ciint cs_etm__get_cpu(u8 trace_chan_id, int *cpu);
1768c2ecf20Sopenharmony_ciint cs_etm__etmq_set_tid(struct cs_etm_queue *etmq,
1778c2ecf20Sopenharmony_ci			 pid_t tid, u8 trace_chan_id);
1788c2ecf20Sopenharmony_cibool cs_etm__etmq_is_timeless(struct cs_etm_queue *etmq);
1798c2ecf20Sopenharmony_civoid cs_etm__etmq_set_traceid_queue_timestamp(struct cs_etm_queue *etmq,
1808c2ecf20Sopenharmony_ci					      u8 trace_chan_id);
1818c2ecf20Sopenharmony_cistruct cs_etm_packet_queue
1828c2ecf20Sopenharmony_ci*cs_etm__etmq_get_packet_queue(struct cs_etm_queue *etmq, u8 trace_chan_id);
1838c2ecf20Sopenharmony_ci#else
1848c2ecf20Sopenharmony_cistatic inline int
1858c2ecf20Sopenharmony_cics_etm__process_auxtrace_info(union perf_event *event __maybe_unused,
1868c2ecf20Sopenharmony_ci			      struct perf_session *session __maybe_unused)
1878c2ecf20Sopenharmony_ci{
1888c2ecf20Sopenharmony_ci	return -1;
1898c2ecf20Sopenharmony_ci}
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_cistatic inline int cs_etm__get_cpu(u8 trace_chan_id __maybe_unused,
1928c2ecf20Sopenharmony_ci				  int *cpu __maybe_unused)
1938c2ecf20Sopenharmony_ci{
1948c2ecf20Sopenharmony_ci	return -1;
1958c2ecf20Sopenharmony_ci}
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_cistatic inline int cs_etm__etmq_set_tid(
1988c2ecf20Sopenharmony_ci				struct cs_etm_queue *etmq __maybe_unused,
1998c2ecf20Sopenharmony_ci				pid_t tid __maybe_unused,
2008c2ecf20Sopenharmony_ci				u8 trace_chan_id __maybe_unused)
2018c2ecf20Sopenharmony_ci{
2028c2ecf20Sopenharmony_ci	return -1;
2038c2ecf20Sopenharmony_ci}
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_cistatic inline bool cs_etm__etmq_is_timeless(
2068c2ecf20Sopenharmony_ci				struct cs_etm_queue *etmq __maybe_unused)
2078c2ecf20Sopenharmony_ci{
2088c2ecf20Sopenharmony_ci	/* What else to return? */
2098c2ecf20Sopenharmony_ci	return true;
2108c2ecf20Sopenharmony_ci}
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_cistatic inline void cs_etm__etmq_set_traceid_queue_timestamp(
2138c2ecf20Sopenharmony_ci				struct cs_etm_queue *etmq __maybe_unused,
2148c2ecf20Sopenharmony_ci				u8 trace_chan_id __maybe_unused) {}
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_cistatic inline struct cs_etm_packet_queue *cs_etm__etmq_get_packet_queue(
2178c2ecf20Sopenharmony_ci				struct cs_etm_queue *etmq __maybe_unused,
2188c2ecf20Sopenharmony_ci				u8 trace_chan_id __maybe_unused)
2198c2ecf20Sopenharmony_ci{
2208c2ecf20Sopenharmony_ci	return NULL;
2218c2ecf20Sopenharmony_ci}
2228c2ecf20Sopenharmony_ci#endif
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci#endif
225