| .. | .. |
|---|
| 8 | 8 | #define INCLUDE__UTIL_PERF_CS_ETM_H__ |
|---|
| 9 | 9 | |
|---|
| 10 | 10 | #include "util/event.h" |
|---|
| 11 | | -#include "util/session.h" |
|---|
| 11 | +#include <linux/bits.h> |
|---|
| 12 | + |
|---|
| 13 | +struct perf_session; |
|---|
| 12 | 14 | |
|---|
| 13 | 15 | /* Versionning header in case things need tro change in the future. That way |
|---|
| 14 | 16 | * decoding of old snapshot is still possible. |
|---|
| .. | .. |
|---|
| 53 | 55 | CS_ETMV4_PRIV_MAX, |
|---|
| 54 | 56 | }; |
|---|
| 55 | 57 | |
|---|
| 58 | +/* |
|---|
| 59 | + * ETMv3 exception encoding number: |
|---|
| 60 | + * See Embedded Trace Macrocell spcification (ARM IHI 0014Q) |
|---|
| 61 | + * table 7-12 Encoding of Exception[3:0] for non-ARMv7-M processors. |
|---|
| 62 | + */ |
|---|
| 63 | +enum { |
|---|
| 64 | + CS_ETMV3_EXC_NONE = 0, |
|---|
| 65 | + CS_ETMV3_EXC_DEBUG_HALT = 1, |
|---|
| 66 | + CS_ETMV3_EXC_SMC = 2, |
|---|
| 67 | + CS_ETMV3_EXC_HYP = 3, |
|---|
| 68 | + CS_ETMV3_EXC_ASYNC_DATA_ABORT = 4, |
|---|
| 69 | + CS_ETMV3_EXC_JAZELLE_THUMBEE = 5, |
|---|
| 70 | + CS_ETMV3_EXC_PE_RESET = 8, |
|---|
| 71 | + CS_ETMV3_EXC_UNDEFINED_INSTR = 9, |
|---|
| 72 | + CS_ETMV3_EXC_SVC = 10, |
|---|
| 73 | + CS_ETMV3_EXC_PREFETCH_ABORT = 11, |
|---|
| 74 | + CS_ETMV3_EXC_DATA_FAULT = 12, |
|---|
| 75 | + CS_ETMV3_EXC_GENERIC = 13, |
|---|
| 76 | + CS_ETMV3_EXC_IRQ = 14, |
|---|
| 77 | + CS_ETMV3_EXC_FIQ = 15, |
|---|
| 78 | +}; |
|---|
| 79 | + |
|---|
| 80 | +/* |
|---|
| 81 | + * ETMv4 exception encoding number: |
|---|
| 82 | + * See ARM Embedded Trace Macrocell Architecture Specification (ARM IHI 0064D) |
|---|
| 83 | + * table 6-12 Possible values for the TYPE field in an Exception instruction |
|---|
| 84 | + * trace packet, for ARMv7-A/R and ARMv8-A/R PEs. |
|---|
| 85 | + */ |
|---|
| 86 | +enum { |
|---|
| 87 | + CS_ETMV4_EXC_RESET = 0, |
|---|
| 88 | + CS_ETMV4_EXC_DEBUG_HALT = 1, |
|---|
| 89 | + CS_ETMV4_EXC_CALL = 2, |
|---|
| 90 | + CS_ETMV4_EXC_TRAP = 3, |
|---|
| 91 | + CS_ETMV4_EXC_SYSTEM_ERROR = 4, |
|---|
| 92 | + CS_ETMV4_EXC_INST_DEBUG = 6, |
|---|
| 93 | + CS_ETMV4_EXC_DATA_DEBUG = 7, |
|---|
| 94 | + CS_ETMV4_EXC_ALIGNMENT = 10, |
|---|
| 95 | + CS_ETMV4_EXC_INST_FAULT = 11, |
|---|
| 96 | + CS_ETMV4_EXC_DATA_FAULT = 12, |
|---|
| 97 | + CS_ETMV4_EXC_IRQ = 14, |
|---|
| 98 | + CS_ETMV4_EXC_FIQ = 15, |
|---|
| 99 | + CS_ETMV4_EXC_END = 31, |
|---|
| 100 | +}; |
|---|
| 101 | + |
|---|
| 102 | +enum cs_etm_sample_type { |
|---|
| 103 | + CS_ETM_EMPTY, |
|---|
| 104 | + CS_ETM_RANGE, |
|---|
| 105 | + CS_ETM_DISCONTINUITY, |
|---|
| 106 | + CS_ETM_EXCEPTION, |
|---|
| 107 | + CS_ETM_EXCEPTION_RET, |
|---|
| 108 | +}; |
|---|
| 109 | + |
|---|
| 110 | +enum cs_etm_isa { |
|---|
| 111 | + CS_ETM_ISA_UNKNOWN, |
|---|
| 112 | + CS_ETM_ISA_A64, |
|---|
| 113 | + CS_ETM_ISA_A32, |
|---|
| 114 | + CS_ETM_ISA_T32, |
|---|
| 115 | +}; |
|---|
| 116 | + |
|---|
| 117 | +struct cs_etm_queue; |
|---|
| 118 | + |
|---|
| 119 | +struct cs_etm_packet { |
|---|
| 120 | + enum cs_etm_sample_type sample_type; |
|---|
| 121 | + enum cs_etm_isa isa; |
|---|
| 122 | + u64 start_addr; |
|---|
| 123 | + u64 end_addr; |
|---|
| 124 | + u32 instr_count; |
|---|
| 125 | + u32 last_instr_type; |
|---|
| 126 | + u32 last_instr_subtype; |
|---|
| 127 | + u32 flags; |
|---|
| 128 | + u32 exception_number; |
|---|
| 129 | + u8 last_instr_cond; |
|---|
| 130 | + u8 last_instr_taken_branch; |
|---|
| 131 | + u8 last_instr_size; |
|---|
| 132 | + u8 trace_chan_id; |
|---|
| 133 | + int cpu; |
|---|
| 134 | +}; |
|---|
| 135 | + |
|---|
| 136 | +#define CS_ETM_PACKET_MAX_BUFFER 1024 |
|---|
| 137 | + |
|---|
| 138 | +/* |
|---|
| 139 | + * When working with per-thread scenarios the process under trace can |
|---|
| 140 | + * be scheduled on any CPU and as such, more than one traceID may be |
|---|
| 141 | + * associated with the same process. Since a traceID of '0' is illegal |
|---|
| 142 | + * as per the CoreSight architecture, use that specific value to |
|---|
| 143 | + * identify the queue where all packets (with any traceID) are |
|---|
| 144 | + * aggregated. |
|---|
| 145 | + */ |
|---|
| 146 | +#define CS_ETM_PER_THREAD_TRACEID 0 |
|---|
| 147 | + |
|---|
| 148 | +struct cs_etm_packet_queue { |
|---|
| 149 | + u32 packet_count; |
|---|
| 150 | + u32 head; |
|---|
| 151 | + u32 tail; |
|---|
| 152 | + u32 instr_count; |
|---|
| 153 | + u64 timestamp; |
|---|
| 154 | + u64 next_timestamp; |
|---|
| 155 | + struct cs_etm_packet packet_buffer[CS_ETM_PACKET_MAX_BUFFER]; |
|---|
| 156 | +}; |
|---|
| 157 | + |
|---|
| 56 | 158 | #define KiB(x) ((x) * 1024) |
|---|
| 57 | 159 | #define MiB(x) ((x) * 1024 * 1024) |
|---|
| 58 | 160 | |
|---|
| 161 | +#define CS_ETM_INVAL_ADDR 0xdeadbeefdeadbeefUL |
|---|
| 162 | + |
|---|
| 163 | +#define BMVAL(val, lsb, msb) ((val & GENMASK(msb, lsb)) >> lsb) |
|---|
| 164 | + |
|---|
| 59 | 165 | #define CS_ETM_HEADER_SIZE (CS_HEADER_VERSION_0_MAX * sizeof(u64)) |
|---|
| 60 | 166 | |
|---|
| 61 | | -static const u64 __perf_cs_etmv3_magic = 0x3030303030303030ULL; |
|---|
| 62 | | -static const u64 __perf_cs_etmv4_magic = 0x4040404040404040ULL; |
|---|
| 167 | +#define __perf_cs_etmv3_magic 0x3030303030303030ULL |
|---|
| 168 | +#define __perf_cs_etmv4_magic 0x4040404040404040ULL |
|---|
| 63 | 169 | #define CS_ETMV3_PRIV_SIZE (CS_ETM_PRIV_MAX * sizeof(u64)) |
|---|
| 64 | 170 | #define CS_ETMV4_PRIV_SIZE (CS_ETMV4_PRIV_MAX * sizeof(u64)) |
|---|
| 65 | 171 | |
|---|
| .. | .. |
|---|
| 67 | 173 | int cs_etm__process_auxtrace_info(union perf_event *event, |
|---|
| 68 | 174 | struct perf_session *session); |
|---|
| 69 | 175 | int cs_etm__get_cpu(u8 trace_chan_id, int *cpu); |
|---|
| 176 | +int cs_etm__etmq_set_tid(struct cs_etm_queue *etmq, |
|---|
| 177 | + pid_t tid, u8 trace_chan_id); |
|---|
| 178 | +bool cs_etm__etmq_is_timeless(struct cs_etm_queue *etmq); |
|---|
| 179 | +void cs_etm__etmq_set_traceid_queue_timestamp(struct cs_etm_queue *etmq, |
|---|
| 180 | + u8 trace_chan_id); |
|---|
| 181 | +struct cs_etm_packet_queue |
|---|
| 182 | +*cs_etm__etmq_get_packet_queue(struct cs_etm_queue *etmq, u8 trace_chan_id); |
|---|
| 70 | 183 | #else |
|---|
| 71 | 184 | static inline int |
|---|
| 72 | 185 | cs_etm__process_auxtrace_info(union perf_event *event __maybe_unused, |
|---|
| .. | .. |
|---|
| 80 | 193 | { |
|---|
| 81 | 194 | return -1; |
|---|
| 82 | 195 | } |
|---|
| 196 | + |
|---|
| 197 | +static inline int cs_etm__etmq_set_tid( |
|---|
| 198 | + struct cs_etm_queue *etmq __maybe_unused, |
|---|
| 199 | + pid_t tid __maybe_unused, |
|---|
| 200 | + u8 trace_chan_id __maybe_unused) |
|---|
| 201 | +{ |
|---|
| 202 | + return -1; |
|---|
| 203 | +} |
|---|
| 204 | + |
|---|
| 205 | +static inline bool cs_etm__etmq_is_timeless( |
|---|
| 206 | + struct cs_etm_queue *etmq __maybe_unused) |
|---|
| 207 | +{ |
|---|
| 208 | + /* What else to return? */ |
|---|
| 209 | + return true; |
|---|
| 210 | +} |
|---|
| 211 | + |
|---|
| 212 | +static inline void cs_etm__etmq_set_traceid_queue_timestamp( |
|---|
| 213 | + struct cs_etm_queue *etmq __maybe_unused, |
|---|
| 214 | + u8 trace_chan_id __maybe_unused) {} |
|---|
| 215 | + |
|---|
| 216 | +static inline struct cs_etm_packet_queue *cs_etm__etmq_get_packet_queue( |
|---|
| 217 | + struct cs_etm_queue *etmq __maybe_unused, |
|---|
| 218 | + u8 trace_chan_id __maybe_unused) |
|---|
| 219 | +{ |
|---|
| 220 | + return NULL; |
|---|
| 221 | +} |
|---|
| 83 | 222 | #endif |
|---|
| 84 | 223 | |
|---|
| 85 | 224 | #endif |
|---|