1#!/usr/bin/env python3 2# 3# Copyright (C) 2024 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18"""etm_types.py: ctypes based structures to handle ocsd_generic_trace_elem from OpenCSD. 19 20 Please refer to the documentation of OpenCSD to see the fields available and their meaning: 21 https://github.com/Linaro/OpenCSD/blob/master/decoder/docs/prog_guide/prog_guide_generic_pkts.md 22 23""" 24 25import ctypes as ct 26from enum import Enum, auto 27import sys 28 29# On 32 bit machines, ocsd_vaddr_t is 32 bit only. 30VADDR_TYPE = ct.c_uint64 if sys.maxsize > 2**32 else ct.c_uint32 31 32 33class SecLevel(Enum): 34 """ocsd_sec_level in OpenCSD.""" 35 SECURE = 0 36 NONSECURE = 1 37 ROOT = 2 38 REALM = 3 39 40 41class ExLevel(Enum): 42 """ocsd_ex_level in OpenCSD.""" 43 UNKNOWN = -1 44 EL0 = 0 45 EL1 = 1 46 EL2 = 2 47 EL3 = 3 48 49 50class PeContext(ct.Structure): 51 """ocsd_pe_context in OpenCSD.""" 52 _fields_ = [("_security_level", ct.c_int), 53 ("_exception_level", ct.c_int), 54 ("context_id", ct.c_uint32), 55 ("vmid", ct.c_uint32), 56 ("bits64", ct.c_uint32, 1), 57 ("ctxt_id_valid", ct.c_uint32, 1), 58 ("vmid_valid", ct.c_uint32, 1), 59 ("el_valid", ct.c_uint32, 1)] 60 61 @property 62 def security_level(self) -> SecLevel: 63 return SecLevel(self._security_level) 64 65 @property 66 def exception_level(self) -> ExLevel: 67 return ExLevel(self._exception_level) 68 69 70class TraceEvent(ct.Structure): 71 """trace_event_t in OpenCSD.""" 72 _fields_ = [("ev_type", ct.c_uint16), 73 ("ev_number", ct.c_uint16)] 74 75 76class TraceOnReason(Enum): 77 """trace_on_reason_t in OpenCSD.""" 78 NORMAL = 0 79 OVERFLOW = 1 80 EX_DEBUG = 2 81 82 83class _SwtInfoInnerStruct(ct.Structure): 84 _fields_ = [("swt_payload_pkt_bitsize", ct.c_uint32, 8), 85 ("swt_payload_num_packets", ct.c_uint32, 8), 86 ("swt_marker_packet", ct.c_uint32, 1), 87 ("swt_has_timestamp", ct.c_uint32, 1), 88 ("swt_marker_first", ct.c_uint32, 1), 89 ("swt_master_err", ct.c_uint32, 1), 90 ("swt_global_err", ct.c_uint32, 1), 91 ("swt_trigger_event", ct.c_uint32, 1), 92 ("swt_frequency", ct.c_uint32, 1), 93 ("swt_id_valid", ct.c_uint32, 1)] 94 95 96class _SwtInfoInnerUnion(ct.Union): 97 _anonymous_ = ("_s",) 98 _fields_ = [("_s", _SwtInfoInnerStruct), 99 ("swt_flag_bits", ct.c_uint32)] 100 101 102class SwtInfo(ct.Structure): 103 """ocsd_swt_info_t in OpenCSD.""" 104 _anonymous_ = ("_u",) 105 _fields_ = [("swt_master_id", ct.c_uint16), 106 ("swt_channel_id", ct.c_uint16), 107 ("_u", _SwtInfoInnerUnion)] 108 109 110class UnsyncInfo(Enum): 111 """unsync_info_t in OpenCSD.""" 112 UNSYNC_UNKNOWN = 0 113 UNSYNC_INIT_DECODER = 1 114 UNSYNC_RESET_DECODER = 2 115 UNSYNC_OVERFLOW = 3 116 UNSYNC_DISCARD = 4 117 UNSYNC_BAD_PACKET = 5 118 UNSYNC_EOT = 6 119 120 121class TraceSyncMarker(Enum): 122 """trace_sync_marker_t in OpenCSD.""" 123 ELEM_MARKER_TS = 0 124 125 126class TraceMarkerPayload(ct.Structure): 127 """trace_marker_payload_t in OpenCSD.""" 128 _fields_ = [("_type", ct.c_int), 129 ("value", ct.c_uint32)] 130 131 @property 132 def type(self) -> TraceSyncMarker: 133 return TraceSyncMarker(self._type) 134 135 136class TraceMemtrans(Enum): 137 """trace_memtrans_t in OpenCSD.""" 138 MEM_TRANS_TRACE_INIT = 0 139 MEM_TRANS_START = 1 140 MEM_TRANS_COMMIT = 2 141 MEM_TRANS_FAIL = 3 142 143 144class TraceSwIte(ct.Structure): 145 """trace_sw_ite_t in OpenCSD.""" 146 _fields_ = [("el", ct.c_uint8), 147 ("value", ct.c_uint64)] 148 149 150class _ElementFlags(ct.Structure): 151 _fields_ = [("last_instr_exec", ct.c_uint32, 1), 152 ("last_instr_sz", ct.c_uint32, 3), 153 ("has_cc", ct.c_uint32, 1), 154 ("cpu_freq_change", ct.c_uint32, 1), 155 ("excep_ret_addr", ct.c_uint32, 1), 156 ("excep_data_marker", ct.c_uint32, 1), 157 ("extended_data", ct.c_uint32, 1), 158 ("has_ts", ct.c_uint32, 1), 159 ("last_instr_cond", ct.c_uint32, 1), 160 ("excep_ret_addr_br_tgt", ct.c_uint32, 1), 161 ("excep_M_tail_chain", ct.c_uint32, 1)] 162 163 164class _ElementFlagsUnion(ct.Union): 165 _anonymous_ = ("_s",) 166 _fields_ = [("_s", _ElementFlags), 167 ("flag_bits", ct.c_uint32)] 168 169 170class _Payload(ct.Union): 171 _fields_ = [("exception_number", ct.c_uint32), 172 ("trace_event", TraceEvent), 173 ("_trace_on_reason", ct.c_int), 174 ("sw_trace_info", SwtInfo), 175 ("num_instr_range", ct.c_uint32), 176 ("_unsync_eot_info", ct.c_int), 177 ("sync_marker", TraceMarkerPayload), 178 ("_mem_trans", ct.c_int), 179 ("sw_ite", TraceSwIte)] 180 181 182class ElemType(Enum): 183 """ocsd_gen_trc_elem_t in OpenCSD.""" 184 UNKNOWN = 0 185 NO_SYNC = 1 186 TRACE_ON = 2 187 EO_TRACE = 3 188 PE_CONTEXT = 4 189 INSTR_RANGE = 5 190 I_RANGE_NOPATH = 6 191 ADDR_NACC = 7 192 ADDR_UNKNOWN = 8 193 EXCEPTION = 9 194 EXCEPTION_RET = 10 195 TIMESTAMP = 11 196 CYCLE_COUNT = 12 197 EVENT = 13 198 SWTRACE = 14 199 SYNC_MARKER = 15 200 MEMTRANS = 16 201 INSTRUMENTATION = 17 202 CUSTOM = 18 203 204 205class IsaType(Enum): 206 """ocsd_isa in OpenCSD.""" 207 ARM = 0 208 THUMB2 = 1 209 AARCH64 = 2 210 TEE = 3 211 JAZELLE = 4 212 CUSTOM = 5 213 UNKNOWN = 6 214 215 216class InstrType(Enum): 217 """ocsd_instr_type in OpenCSD.""" 218 OTHER = 0 219 BR = 1 220 BR_INDIRECT = 2 221 ISB = 3 222 DSB_DMB = 4 223 WFI_WFE = 5 224 TSTART = 6 225 226 227class InstrSubtype(Enum): 228 """ocsd_instr_subtype in OpenCSD.""" 229 NONE = 0 230 BR_LINK = 1 231 V8_RET = 2 232 V8_ERET = 3 233 V7_IMPLIED_RET = 4 234 235 236class GenericTraceElement(ct.Structure): 237 """ocsd_generic_trace_elem in OpenCSD.""" 238 _anonymous_ = ("_payload", "_flags") 239 _fields_ = [("_elem_type", ct.c_int), 240 ("_isa", ct.c_int), 241 ("st_addr", VADDR_TYPE), 242 ("en_addr", VADDR_TYPE), 243 ("context", PeContext), 244 ("timestamp", ct.c_uint64), 245 ("cycle_count", ct.c_uint32), 246 ("_last_i_type", ct.c_int), 247 ("_last_i_subtype", ct.c_int), 248 ("_flags", _ElementFlagsUnion), 249 ("_payload", _Payload), 250 ("ptr_extended_data", ct.c_void_p)] 251 252 @property 253 def elem_type(self) -> ElemType: 254 return ElemType(self._elem_type) 255 256 @property 257 def isa(self) -> IsaType: 258 return IsaType(self._isa) 259 260 @property 261 def last_i_type(self) -> InstrType: 262 return InstrType(self._last_i_type) 263 264 @property 265 def last_i_subtype(self) -> InstrSubtype: 266 return InstrSubtype(self._last_i_subtype) 267 268 @property 269 def trace_on_reason(self) -> TraceOnReason: 270 # This is from the anonymous structure that is called _Payload in _fields_. 271 return TraceOnReason(self._trace_on_reason) 272 273 @property 274 def unsync_eot_info(self) -> UnsyncInfo: 275 # This is from the anonymous structure that is called _Payload in _fields_. 276 return UnsyncInfo(self._unsync_eot_info) 277 278 @property 279 def mem_trans(self) -> TraceMemtrans: 280 # This is from the anonymous structure that is called _Payload in _fields_. 281 return TraceMemtrans(self._mem_trans) 282 283 def exception_type(self) -> str: 284 """Return the exception type indicated by exception_number.""" 285 # The values are taken from the Arm Architecture Reference Manual for A-profile, "D5.3.30 286 # Exception 64-bit Address IS0 Packet". The reasons for generating them are listed in 287 # "D4.4.4 Exceptions to Exception element encoding". 288 names = ["PE Reset", "Debug halt", "Call", "Trap", "System Error", "Unknown", 289 "Inst debug", "Data debug", "Unknown", "Unknown", 290 "Alignment", "Inst Fault", "Data Fault", "Unknown", 291 "IRQ", "FIQ", 292 "Implementation defined 0", "Implementation defined 1", 293 "Implementation defined 2", "Implementation defined 3", 294 "Implementation defined 4", "Implementation defined 5", 295 "Implementation defined 6", "Implementation defined 7", 296 "Reserved"] 297 if self.exception_number < len(names): 298 return names[self.exception_number] 299 300 return "Reserved" 301