diff --git a/contrib/opencsd/decoder/include/common/ocsd_dcd_mngr.h b/contrib/opencsd/decoder/include/common/ocsd_dcd_mngr.h index 3342eacb24ca..34c4ef1dc1c4 100644 --- a/contrib/opencsd/decoder/include/common/ocsd_dcd_mngr.h +++ b/contrib/opencsd/decoder/include/common/ocsd_dcd_mngr.h @@ -80,16 +80,16 @@ class DecoderMngrBase : public IDecoderMngr private: - ocsd_trace_protocol_t m_builtInProtocol; //!< Protocol ID if built in type. + const ocsd_trace_protocol_t m_builtInProtocol; //!< Protocol ID if built in type. }; template -DecoderMngrBase::DecoderMngrBase(const std::string &decoderTypeName, ocsd_trace_protocol_t builtInProtocol) + DecoderMngrBase::DecoderMngrBase(const std::string &decoderTypeName, ocsd_trace_protocol_t builtInProtocol) : + m_builtInProtocol(builtInProtocol) { OcsdLibDcdRegister *pDcdReg = OcsdLibDcdRegister::getDecoderRegister(); if(pDcdReg) pDcdReg->registerDecoderTypeByName(decoderTypeName,this); - m_builtInProtocol = builtInProtocol; } template @@ -362,6 +362,49 @@ class DecodeMngrFullDcd : public DecoderMngrBase } }; +/* full decode - extended config object - base + derived. */ +template< class P, // Packet class. + class Pt, // Packet enum type ID. + class Pc, // Processor config base class. + class PcEx, // Processor config derived class + class PcSt, // Processor config struct type + class PktProc, // Packet processor class. + class PktDcd> // Packet decoder class. + class DecodeMngrFullDcdExCfg : public DecoderMngrBase +{ +public: + DecodeMngrFullDcdExCfg(const std::string &name, ocsd_trace_protocol_t builtInProtocol) + : DecoderMngrBase(name, builtInProtocol) {}; + + virtual ~DecodeMngrFullDcdExCfg() {}; + + virtual TraceComponent *createPktProc(const bool useInstID, const int instID) + { + TraceComponent *pComp; + if (useInstID) + pComp = new (std::nothrow) PktProc(instID); + else + pComp = new (std::nothrow) PktProc(); + return pComp; + } + + virtual TraceComponent *createPktDecode(const bool useInstID, const int instID) + { + TraceComponent *pComp; + if (useInstID) + pComp = new (std::nothrow)PktDcd(instID); + else + pComp = new (std::nothrow)PktDcd(); + return pComp; + } + + virtual CSConfig *createConfig(const void *pDataStruct) + { + return new (std::nothrow) PcEx((PcSt *)pDataStruct); + } +}; + + /****************************************************************************************************/ /* Packet processor only, templated base for creating decoder objects */ /****************************************************************************************************/ diff --git a/contrib/opencsd/decoder/include/common/ocsd_dcd_tree.h b/contrib/opencsd/decoder/include/common/ocsd_dcd_tree.h index e4e74f2bc659..b1c3dc601cab 100644 --- a/contrib/opencsd/decoder/include/common/ocsd_dcd_tree.h +++ b/contrib/opencsd/decoder/include/common/ocsd_dcd_tree.h @@ -168,6 +168,30 @@ class DecodeTree : public ITrcDataIn */ ocsd_err_t removeDecoder(const uint8_t CSID); + /*! + * Get the stats block for the channel indicated. + * Caller must check p_stats_block->version to esure that the block + * is filled in a compatible manner. + * + * @param CSID : Configured CoreSight trace ID for the decoder. + * @param p_stats_block: block pointer to set to reference the stats block. + * + * @return ocsd_err_t : Library error code - OCSD_OK if valid block pointer returned, + * OCSD_ERR_NOTINIT if decoder does not support stats counting. + */ + ocsd_err_t getDecoderStats(const uint8_t CSID, ocsd_decode_stats_t **p_stats_block); + + /*! + * Reset the stats block for the chosens decode channel. + * stats block is reset independently of the decoder reset to allow counts across + * multiple decode runs. + * + * @param handle : Handle to decode tree. + * @param CSID : Configured CoreSight trace ID for the decoder. + * + * @return ocsd_err_t : Library error code - OCSD_OK if successful. + */ + ocsd_err_t resetDecoderStats(const uint8_t CSID); /* get decoder elements currently in use */ @@ -387,7 +411,7 @@ class DecodeTree : public ITrcDataIn void destroyMemAccMapper(); ocsd_err_t initCallbackMemAcc(const ocsd_vaddr_t st_address, const ocsd_vaddr_t en_address, const ocsd_mem_space_acc_t mem_space, void *p_cb_func, bool IDfn, const void *p_context); - + TrcPktProcI *getPktProcI(const uint8_t CSID); ocsd_dcd_tree_src_t m_dcd_tree_type; @@ -417,6 +441,9 @@ class DecodeTree : public ITrcDataIn /**! default instruction decoder */ static TrcIDecode s_instruction_decoder; + + /**! demux stats block */ + ocsd_demux_stats_t m_demux_stats; }; /** @}*/ diff --git a/contrib/opencsd/decoder/include/common/ocsd_error.h b/contrib/opencsd/decoder/include/common/ocsd_error.h index e547f4878033..7c6ed3af141f 100644 --- a/contrib/opencsd/decoder/include/common/ocsd_error.h +++ b/contrib/opencsd/decoder/include/common/ocsd_error.h @@ -108,6 +108,17 @@ inline ocsdError& ocsdError::operator=(const ocsdError &err) return (*this = &err); } +/* class to get data path response values as strings */ +class ocsdDataRespStr +{ +public: + ocsdDataRespStr(ocsd_datapath_resp_t type) { m_type = type; } + ~ocsdDataRespStr() {}; + + const char* getStr(); +private: + ocsd_datapath_resp_t m_type; +}; /** @}*/ diff --git a/contrib/opencsd/decoder/include/common/trc_core_arch_map.h b/contrib/opencsd/decoder/include/common/trc_core_arch_map.h index b72b4b411fa4..aa976c39f908 100644 --- a/contrib/opencsd/decoder/include/common/trc_core_arch_map.h +++ b/contrib/opencsd/decoder/include/common/trc_core_arch_map.h @@ -53,7 +53,8 @@ * * Valid architecture profile names are:- * - ARMv7-A, ARMv7-R, ARMv7-M; - * - ARMv8-A, ARMv8.3A, ARMv8-R, ARMv8-M; + * - ARMv8-A, ARMv8.x-A, ARMv8-R, ARMv8-M; + * - ARM-AA64, ARM-aa64 * */ class CoreArchProfileMap @@ -65,36 +66,12 @@ class CoreArchProfileMap ocsd_arch_profile_t getArchProfile(const std::string &coreName); private: + ocsd_arch_profile_t getPatternMatchCoreName(const std::string &coreName); std::map core_profiles; std::map arch_profiles; }; -inline ocsd_arch_profile_t CoreArchProfileMap::getArchProfile(const std::string &coreName) -{ - ocsd_arch_profile_t ap = { ARCH_UNKNOWN, profile_Unknown }; - bool bFound = false; - - std::map::const_iterator it; - - /* match against the core name map. */ - it = core_profiles.find(coreName); - if (it != core_profiles.end()) - { - ap = it->second; - bFound = true; - } - - /* scan architecture profiles on no core name match */ - if (!bFound) - { - it = arch_profiles.find(coreName); - if (it != arch_profiles.end()) - ap = it->second; - } - return ap; -} - #endif // ARM_TRC_CORE_ARCH_MAP_H_INCLUDED /* End of File trc_core_arch_map.h */ diff --git a/contrib/opencsd/decoder/include/common/trc_frame_deformatter.h b/contrib/opencsd/decoder/include/common/trc_frame_deformatter.h index e4297a41e8fd..cb2960fcdd07 100644 --- a/contrib/opencsd/decoder/include/common/trc_frame_deformatter.h +++ b/contrib/opencsd/decoder/include/common/trc_frame_deformatter.h @@ -73,6 +73,9 @@ class TraceFormatterFrameDecoder : public ITrcDataIn componentAttachPt *getErrLogAttachPt(); + /* init decoder implementation object */ + ocsd_err_t Init(); + /* configuration - set operational mode for incoming stream (has FSYNCS etc) */ ocsd_err_t Configure(uint32_t cfg_flags); const uint32_t getConfigFlags() const; @@ -85,9 +88,13 @@ class TraceFormatterFrameDecoder : public ITrcDataIn ocsd_datapath_resp_t Reset(); /* reset the decode to the start state, drop partial data - propogate to attached components */ ocsd_datapath_resp_t Flush(); /* flush existing data if possible, retain state - propogate to attached components */ + /* demux stats */ + void SetDemuxStatsBlock(ocsd_demux_stats_t *pStatsBlock); + private: TraceFmtDcdImpl *m_pDecoder; int m_instNum; + }; /** @}*/ diff --git a/contrib/opencsd/decoder/include/common/trc_gen_elem.h b/contrib/opencsd/decoder/include/common/trc_gen_elem.h index 5d8983a8c274..405abfef8341 100644 --- a/contrib/opencsd/decoder/include/common/trc_gen_elem.h +++ b/contrib/opencsd/decoder/include/common/trc_gen_elem.h @@ -69,19 +69,22 @@ class OcsdTraceElement : public trcPrintableElem, public ocsd_generic_trace_elem void setExcepMarker() { excep_data_marker = 1; }; void setExceptionNum(uint32_t excepNum) { exception_number = excepNum; }; - - void setTraceOnReason(const trace_on_reason_t reason); void setUnSyncEOTReason(const unsync_info_t reason); + void setTransactionType(const trace_memtrans_t trans) { mem_trans = trans; }; void setAddrRange(const ocsd_vaddr_t st_addr, const ocsd_vaddr_t en_addr, const int num_instr = 1); void setLastInstrInfo(const bool exec, const ocsd_instr_type last_i_type, const ocsd_instr_subtype last_i_subtype, const uint8_t size); - void setAddrStart(const ocsd_vaddr_t st_addr) { this->st_addr = st_addr; }; + void setAddrStart(const ocsd_vaddr_t st_addr) { this->st_addr = st_addr; }; void setLastInstrCond(const int is_cond) { this->last_instr_cond = is_cond; }; void setSWTInfo(const ocsd_swt_info_t swt_info) { sw_trace_info = swt_info; }; void setExtendedDataPtr(const void *data_ptr); + void setITEInfo(const trace_sw_ite_t sw_instrumentation) { sw_ite = sw_instrumentation; }; + + void setSyncMarker(const trace_marker_payload_t &marker); + // stringize the element virtual void toString(std::string &str) const; @@ -208,6 +211,11 @@ inline void OcsdTraceElement::setExtendedDataPtr(const void *data_ptr) ptr_extended_data = data_ptr; } +inline void OcsdTraceElement::setSyncMarker(const trace_marker_payload_t &marker) +{ + sync_marker = marker; +} + // set persistent data between output packets. inline void OcsdTraceElement::copyPersistentData(const OcsdTraceElement &src) { diff --git a/contrib/opencsd/decoder/include/common/trc_pkt_decode_base.h b/contrib/opencsd/decoder/include/common/trc_pkt_decode_base.h index da702068f372..24ea2b05a6f9 100644 --- a/contrib/opencsd/decoder/include/common/trc_pkt_decode_base.h +++ b/contrib/opencsd/decoder/include/common/trc_pkt_decode_base.h @@ -96,6 +96,7 @@ class TrcPktDecodeI : public TraceComponent /* target access */ ocsd_err_t accessMemory(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, uint32_t *num_bytes, uint8_t *p_buffer); + ocsd_err_t invalidateMemAccCache(); /* instruction decode */ ocsd_err_t instrDecode(ocsd_instr_info *instr_info); @@ -180,6 +181,14 @@ inline ocsd_err_t TrcPktDecodeI::accessMemory(const ocsd_vaddr_t address, const return OCSD_ERR_DCD_INTERFACE_UNUSED; } +inline ocsd_err_t TrcPktDecodeI::invalidateMemAccCache() +{ + if (!m_uses_memaccess) + return OCSD_ERR_DCD_INTERFACE_UNUSED; + m_mem_access.first()->InvalidateMemAccCache(getCoreSightTraceID()); + return OCSD_OK; +} + /**********************************************************************/ template class TrcPktDecodeBase : public TrcPktDecodeI, public IPktDataIn

diff --git a/contrib/opencsd/decoder/include/common/trc_pkt_proc_base.h b/contrib/opencsd/decoder/include/common/trc_pkt_proc_base.h index 3098a3d0c0ea..8ed7d83b2d5a 100644 --- a/contrib/opencsd/decoder/include/common/trc_pkt_proc_base.h +++ b/contrib/opencsd/decoder/include/common/trc_pkt_proc_base.h @@ -43,6 +43,7 @@ #include "trc_component.h" #include "comp_attach_pt_t.h" +#include "opencsd/ocsd_if_version.h" /** @defgroup ocsd_pkt_proc OpenCSD Library : Packet Processors. @brief Classes providing Protocol Packet Processing capability. @@ -76,6 +77,8 @@ class TrcPktProcI : public TraceComponent, public ITrcDataIn const uint8_t *pDataBlock, uint32_t *numBytesProcessed) = 0; + virtual ocsd_err_t getStatsBlock(ocsd_decode_stats_t **pp_stats) = 0; + virtual void resetStats() = 0; protected: /* implementation packet processing interface */ @@ -155,6 +158,10 @@ class TrcPktProcBase : public TrcPktProcI //!< Get the configuration for the decoder. virtual const Pc *getProtocolConfig() const { return m_config; }; +/* stats block access - derived class must init stats for the block to be returned. */ + virtual ocsd_err_t getStatsBlock(ocsd_decode_stats_t **pp_stats); + virtual void resetStats(); /* reset the counts - operates separately from decoder reset. */ + protected: /* data output functions */ @@ -183,6 +190,14 @@ class TrcPktProcBase : public TrcPktProcI const bool checkInit(); // return true if init (configured and at least one output sink attached), false otherwise. + /* stats block updates - called by derived protocol specific decoder */ + void statsAddTotalCount(const uint64_t count) { m_stats.channel_total += count; }; + void statsAddUnsyncCount(const uint64_t count) { m_stats.channel_unsynced += count; }; + void statsAddBadSeqCount(const uint32_t count) { m_stats.bad_sequence_errs += count; }; + void statsAddBadHdrCount(const uint32_t count) { m_stats.bad_header_errs += count; }; + void statsInit() { m_stats_init = true; }; /* mark stats as in use */ + + private: /* decode control */ ocsd_datapath_resp_t Reset(const ocsd_trc_index_t index); @@ -195,20 +210,29 @@ class TrcPktProcBase : public TrcPktProcI componentAttachPt> m_pkt_indexer_i; bool m_b_is_init; + + /* decode statistics block */ + ocsd_decode_stats_t m_stats; + bool m_stats_init; /*< true if the specific decoder is using the stats */ + }; template TrcPktProcBase::TrcPktProcBase(const char *component_name) : TrcPktProcI(component_name), m_config(0), - m_b_is_init(false) + m_b_is_init(false), + m_stats_init(false) { + resetStats(); } template TrcPktProcBase::TrcPktProcBase(const char *component_name, int instIDNum) : TrcPktProcI(component_name, instIDNum), m_config(0), - m_b_is_init(false) + m_b_is_init(false), + m_stats_init(false) { + resetStats(); } template TrcPktProcBase::~TrcPktProcBase() @@ -405,6 +429,26 @@ template const bool TrcPktProcBase::check return m_b_is_init; } +template ocsd_err_t TrcPktProcBase::getStatsBlock(ocsd_decode_stats_t **pp_stats) +{ + + *pp_stats = &m_stats; + return m_stats_init ? OCSD_OK : OCSD_ERR_NOT_INIT; +} + +template void TrcPktProcBase::resetStats() +{ + m_stats.version = OCSD_VER_NUM; + m_stats.revision = OCSD_STATS_REVISION; + m_stats.channel_total = 0; + m_stats.channel_unsynced = 0; + m_stats.bad_header_errs = 0; + m_stats.bad_sequence_errs = 0; + m_stats.demux.frame_bytes = 0; + m_stats.demux.no_id_bytes = 0; + m_stats.demux.valid_id_bytes = 0; +} + /** @}*/ #endif // ARM_TRC_PKT_PROC_BASE_H_INCLUDED diff --git a/contrib/opencsd/decoder/include/i_dec/trc_idec_arminst.h b/contrib/opencsd/decoder/include/i_dec/trc_idec_arminst.h index 911b0cf7db95..e90ec04ae84d 100644 --- a/contrib/opencsd/decoder/include/i_dec/trc_idec_arminst.h +++ b/contrib/opencsd/decoder/include/i_dec/trc_idec_arminst.h @@ -44,7 +44,7 @@ /* supplementary decode information */ struct decode_info { - uint16_t arch_version; + ocsd_arch_version_t arch_version; ocsd_instr_subtype instr_sub_type; }; @@ -121,7 +121,8 @@ arm_barrier_t inst_A64_barrier(uint32_t inst); int inst_ARM_wfiwfe(uint32_t inst); int inst_Thumb_wfiwfe(uint32_t inst); -int inst_A64_wfiwfe(uint32_t inst); +int inst_A64_wfiwfe(uint32_t inst, struct decode_info *info); +int inst_A64_Tstart(uint32_t inst); /* Test whether an instruction is definitely undefined, e.g. because diff --git a/contrib/opencsd/decoder/include/interfaces/trc_pkt_raw_in_i.h b/contrib/opencsd/decoder/include/interfaces/trc_pkt_raw_in_i.h index 6f7b21383024..dfa7e057ca67 100644 --- a/contrib/opencsd/decoder/include/interfaces/trc_pkt_raw_in_i.h +++ b/contrib/opencsd/decoder/include/interfaces/trc_pkt_raw_in_i.h @@ -47,7 +47,7 @@ * * This interface provides a monitor point for the packet processor block. * The templated interface is called with a complete packet of the given - * type, plus the raw packet bytes. Use for tools which need to display compplete + * type, plus the raw packet bytes. Use for tools which need to display complete * packets or require additional processing on raw packet data. * * This interface is not part of the data decode path and cannot provide feedback. diff --git a/contrib/opencsd/decoder/include/interfaces/trc_tgt_mem_access_i.h b/contrib/opencsd/decoder/include/interfaces/trc_tgt_mem_access_i.h index effc9b5e161e..68a4e10055d4 100644 --- a/contrib/opencsd/decoder/include/interfaces/trc_tgt_mem_access_i.h +++ b/contrib/opencsd/decoder/include/interfaces/trc_tgt_mem_access_i.h @@ -83,6 +83,14 @@ class ITargetMemAccess const ocsd_mem_space_acc_t mem_space, uint32_t *num_bytes, uint8_t *p_buffer) = 0; + + /*! + * Invalidate any caching that the memory accessor functions are using. + * Generally called when a memory context changes in the trace. + * + * @param cs_trace_id : protocol source trace ID. + */ + virtual void InvalidateMemAccCache(const uint8_t cs_trace_id) = 0; }; diff --git a/contrib/opencsd/decoder/include/mem_acc/trc_mem_acc_mapper.h b/contrib/opencsd/decoder/include/mem_acc/trc_mem_acc_mapper.h index a700e9dbd07e..4a08498df14e 100644 --- a/contrib/opencsd/decoder/include/mem_acc/trc_mem_acc_mapper.h +++ b/contrib/opencsd/decoder/include/mem_acc/trc_mem_acc_mapper.h @@ -61,6 +61,8 @@ class TrcMemAccMapper : public ITargetMemAccess uint32_t *num_bytes, uint8_t *p_buffer); + virtual void InvalidateMemAccCache(const uint8_t cs_trace_id); + // mapper memory area configuration interface // add an accessor to this map diff --git a/contrib/opencsd/decoder/include/opencsd.h b/contrib/opencsd/decoder/include/opencsd.h index 615bbcafa2d9..8af4fd0df5ef 100644 --- a/contrib/opencsd/decoder/include/opencsd.h +++ b/contrib/opencsd/decoder/include/opencsd.h @@ -63,6 +63,7 @@ #include "opencsd/etmv4/etmv4_decoder.h" #include "opencsd/ptm/ptm_decoder.h" #include "opencsd/stm/stm_decoder.h" +#include "opencsd/ete/ete_decoder.h" /** C++ library object types */ #include "common/ocsd_error_logger.h" diff --git a/contrib/opencsd/decoder/include/opencsd/c_api/ocsd_c_api_types.h b/contrib/opencsd/decoder/include/opencsd/c_api/ocsd_c_api_types.h index cde351fc525f..7f9b4bab9494 100644 --- a/contrib/opencsd/decoder/include/opencsd/c_api/ocsd_c_api_types.h +++ b/contrib/opencsd/decoder/include/opencsd/c_api/ocsd_c_api_types.h @@ -46,6 +46,7 @@ #include "opencsd/etmv4/trc_pkt_types_etmv4.h" #include "opencsd/ptm/trc_pkt_types_ptm.h" #include "opencsd/stm/trc_pkt_types_stm.h" +#include "opencsd/ete/trc_pkt_types_ete.h" /** @ingroup lib_c_api @{*/ diff --git a/contrib/opencsd/decoder/include/opencsd/c_api/opencsd_c_api.h b/contrib/opencsd/decoder/include/opencsd/c_api/opencsd_c_api.h index 90201d436e08..ebbba87d952e 100644 --- a/contrib/opencsd/decoder/include/opencsd/c_api/opencsd_c_api.h +++ b/contrib/opencsd/decoder/include/opencsd/c_api/opencsd_c_api.h @@ -210,10 +210,36 @@ OCSD_C_API ocsd_err_t ocsd_dt_attach_packet_callback( const dcd_tree_handle_t h const void *p_context); - - +/*! + * Get the stats block for the channel indicated. + * Caller must check p_stats_block->version to esure that the block + * is filled in a compatible manner. + * + * @param handle : Handle to decode tree. + * @param CSID : Configured CoreSight trace ID for the decoder. + * @param p_stats_block: block pointer to set to reference the stats block. + * + * @return ocsd_err_t : Library error code - OCSD_OK if valid block pointer returned, + * OCSD_ERR_NOTINIT if decoder does not support stats counting. + */ +OCSD_C_API ocsd_err_t ocsd_dt_get_decode_stats( const dcd_tree_handle_t handle, + const unsigned char CSID, + ocsd_decode_stats_t **p_stats_block); - + +/*! + * Reset the stats block for the chosens decode channel. + * stats block is reset independently of the decoder reset to allow counts across + * multiple decode runs. + * + * @param handle : Handle to decode tree. + * @param CSID : Configured CoreSight trace ID for the decoder. + * + * @return ocsd_err_t : Library error code - OCSD_OK if successful. + */ +OCSD_C_API ocsd_err_t ocsd_dt_reset_decode_stats( const dcd_tree_handle_t handle, + const unsigned char CSID); + /** @}*/ /*---------------------- Memory Access for traced opcodes ----------------------------------------------------------------------------------*/ /** @name Library Memory Accessor configuration on decode tree. @@ -373,6 +399,28 @@ OCSD_C_API ocsd_err_t ocsd_def_errlog_set_strprint_cb(const dcd_tree_handle_t ha */ OCSD_C_API void ocsd_def_errlog_msgout(const char *msg); +/*! + * Convert an error code into a string. + * + * @param err : error code. + * @param buffer : buffer for return string + * @param buffer_size : length of buffer. + */ +OCSD_C_API void ocsd_err_str(const ocsd_err_t err, char *buffer, const int buffer_size); + +/*! + * returns the last error logged by the system, with the related trace byte index, trace channel id, + * and any error message related string. + * If index or channel ID are not valid these will return OCSD_BAD_TRC_INDEX and OCSD_BAD_CS_SRC_ID. + * + * return value is the error code of the last logged error, OCSD_OK for no error available. + * + * @param index : returns trace byte index relating to error, or OCSD_BAD_TRC_INDEX + * @param chan_id : returns trace channel ID relating to error, or OCSD_BAD_CS_SRC_ID + * @param message : buffer to copy the last error message. + * @param message_len: length of message buffer. + */ +OCSD_C_API ocsd_err_t ocsd_get_last_err(ocsd_trc_index_t *index, uint8_t *chan_id, char *message, const int message_len); /** @}*/ diff --git a/contrib/opencsd/decoder/include/opencsd/ete/ete_decoder.h b/contrib/opencsd/decoder/include/opencsd/ete/ete_decoder.h new file mode 100644 index 000000000000..ba0d718bfff1 --- /dev/null +++ b/contrib/opencsd/decoder/include/opencsd/ete/ete_decoder.h @@ -0,0 +1,47 @@ +/* +* \file ete_decoder.h +* \brief OpenCSD : Top level header file for ETE decoder. +* +* \copyright Copyright (c) 2019, ARM Limited. All Rights Reserved. +*/ + +/* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software without +* specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef ARM_ETE_DECODER_H_INCLUDED +#define ARM_ETE_DECODER_H_INCLUDED + +// ETE actually uses extended ETMv4 packet processor and decode +// ETE specifics limited to configuration +// +#include "trc_cmp_cfg_ete.h" +#include "trc_pkt_types_ete.h" + +#endif // ARM_ETE_DECODER_H_INCLUDED + +/* End of File ete_decoder.h */ + diff --git a/contrib/opencsd/decoder/include/opencsd/ete/trc_cmp_cfg_ete.h b/contrib/opencsd/decoder/include/opencsd/ete/trc_cmp_cfg_ete.h new file mode 100644 index 000000000000..8365ffa88460 --- /dev/null +++ b/contrib/opencsd/decoder/include/opencsd/ete/trc_cmp_cfg_ete.h @@ -0,0 +1,81 @@ +/* +* \file trc_cmp_cfg_ete.h +* \brief OpenCSD : ETE configuration +* +* \copyright Copyright (c) 2019, ARM Limited. All Rights Reserved. +*/ + +/* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software without +* specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef ARM_TRC_CMP_CFG_ETE_H_INCLUDED +#define ARM_TRC_CMP_CFG_ETE_H_INCLUDED + +#include "trc_pkt_types_ete.h" +#include "opencsd/etmv4/trc_cmp_cfg_etmv4.h" + +/** @addtogroup ocsd_protocol_cfg +@{*/ + +/** @name ETE configuration +@{*/ + +/*! + * @class ETEConfig + * @brief Interpreter class for ETE config structure + * + * ETE trace and config are a superset of ETMv4 trace and config - hence + * use the EtmV4Config class as a base. + */ +class ETEConfig : public EtmV4Config +{ +public: + ETEConfig(); + ETEConfig(const ocsd_ete_cfg *cfg_regs); + ~ETEConfig(); + + //! copy assignment operator for base structure into class. + ETEConfig & operator=(const ocsd_ete_cfg *p_cfg); + + //! cast operator returning struct const reference + operator const ocsd_ete_cfg &() const { return m_ete_cfg; }; + //! cast operator returning struct const pointer + operator const ocsd_ete_cfg *() const { return &m_ete_cfg; }; + +private: + void copyV4(); // copy relevent config to underlying structure. + + ocsd_ete_cfg m_ete_cfg; +}; + + +/** @}*/ +/** @}*/ + +#endif // ARM_TRC_CMP_CFG_ETE_H_INCLUDED + +/* End of File trc_cmp_cfg_ete.h */ diff --git a/contrib/opencsd/decoder/include/opencsd/ete/trc_dcd_mngr_ete.h b/contrib/opencsd/decoder/include/opencsd/ete/trc_dcd_mngr_ete.h new file mode 100644 index 000000000000..7b0c134b20c5 --- /dev/null +++ b/contrib/opencsd/decoder/include/opencsd/ete/trc_dcd_mngr_ete.h @@ -0,0 +1,58 @@ +/* +* \file trc_dcd_mngr_ete.h +* \brief OpenCSD : ETE decoder creation. +* +* \copyright Copyright (c) 2019, ARM Limited. All Rights Reserved. +*/ + +/* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software without +* specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef ARM_TRC_DCD_MNGR_ETE_H_INCLUDED +#define ARM_TRC_DCD_MNGR_ETE_H_INCLUDED + +#include "common/ocsd_dcd_mngr.h" +#include "trc_cmp_cfg_ete.h" +#include "opencsd/etmv4/trc_pkt_decode_etmv4i.h" +#include "opencsd/etmv4/trc_pkt_proc_etmv4.h" + +class DecoderMngrETE : public DecodeMngrFullDcdExCfg< EtmV4ITrcPacket, + ocsd_etmv4_i_pkt_type, + EtmV4Config, + ETEConfig, + ocsd_ete_cfg, + TrcPktProcEtmV4I, + TrcPktDecodeEtmV4I> +{ +public: + DecoderMngrETE(const std::string &name) : DecodeMngrFullDcdExCfg(name, OCSD_PROTOCOL_ETE) {}; + virtual ~DecoderMngrETE() {}; +}; + +#endif // ARM_TRC_DCD_MNGR_ETE_H_INCLUDED + +/* End of File trc_dcd_mngr_ete.h */ diff --git a/contrib/opencsd/decoder/include/opencsd/ete/trc_pkt_types_ete.h b/contrib/opencsd/decoder/include/opencsd/ete/trc_pkt_types_ete.h new file mode 100644 index 000000000000..f87d454605fd --- /dev/null +++ b/contrib/opencsd/decoder/include/opencsd/ete/trc_pkt_types_ete.h @@ -0,0 +1,66 @@ +/* + * \file trc_pkt_types_ete.h + * \brief OpenCSD : ETE types + * + * \copyright Copyright (c) 2019, ARM Limited. All Rights Reserved. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ARM_TRC_PKT_TYPES_ETE_H_INCLUDED +#define ARM_TRC_PKT_TYPES_ETE_H_INCLUDED + +#include "opencsd/trc_pkt_types.h" +#include "opencsd/etmv4/trc_pkt_types_etmv4.h" + /** @addtogroup trc_pkts + @{*/ + + /** @name ETE config Types + @{*/ + + +typedef struct _ocsd_ete_cfg +{ + uint32_t reg_idr0; /**< ID0 register */ + uint32_t reg_idr1; /**< ID1 register */ + uint32_t reg_idr2; /**< ID2 register */ + uint32_t reg_idr8; /**< ID8 - maxspec */ + uint32_t reg_devarch; /**< DevArch register */ + uint32_t reg_configr; /**< Config Register */ + uint32_t reg_traceidr; /**< Trace Stream ID register */ + ocsd_arch_version_t arch_ver; /**< Architecture version */ + ocsd_core_profile_t core_prof; /**< Core Profile */ +} ocsd_ete_cfg; + + +/** @}*/ +/** @}*/ + +#endif // ARM_TRC_PKT_TYPES_ETE_H_INCLUDED + +/* End of File trc_pkt_types_ete.h */ diff --git a/contrib/opencsd/decoder/include/opencsd/etmv4/trc_cmp_cfg_etmv4.h b/contrib/opencsd/decoder/include/opencsd/etmv4/trc_cmp_cfg_etmv4.h index 1d72d97afe59..223dbda44510 100644 --- a/contrib/opencsd/decoder/include/opencsd/etmv4/trc_cmp_cfg_etmv4.h +++ b/contrib/opencsd/decoder/include/opencsd/etmv4/trc_cmp_cfg_etmv4.h @@ -81,6 +81,7 @@ class EtmV4Config : public CSConfig // public ocsd_etmv4_cfg const bool hasCycleCountI() const; const bool hasRetStack() const; const uint8_t numEvents() const; + const bool eteHasTSMarker() const; typedef enum _condType { COND_PASS_FAIL, @@ -104,6 +105,7 @@ class EtmV4Config : public CSConfig // public ocsd_etmv4_cfg const uint32_t TimeStampSize() const; const bool commitOpt1() const; + const bool commTransP0() const; /* idr 1 */ const uint8_t MajVersion() const; @@ -151,6 +153,7 @@ class EtmV4Config : public CSConfig // public ocsd_etmv4_cfg const bool enabledCCI() const; const bool enabledCID() const; const bool enabledVMID() const; + const bool enabledVMIDOpt() const; typedef enum { COND_TR_DIS, @@ -253,6 +256,11 @@ inline const bool EtmV4Config::hasTrcExcpData() const return (bool)((m_cfg.reg_idr0 & 0x20000) == 0x20000); } +inline const bool EtmV4Config::eteHasTSMarker() const +{ + return (FullVersion() >= 0x51) && ((m_cfg.reg_idr0 & 0x800000) == 0x800000); +} + inline const uint32_t EtmV4Config::TimeStampSize() const { uint32_t tsSizeF = (m_cfg.reg_idr0 >> 24) & 0x1F; @@ -268,6 +276,11 @@ inline const bool EtmV4Config::commitOpt1() const return (bool)((m_cfg.reg_idr0 & 0x20000000) == 0x20000000) && hasCycleCountI(); } +inline const bool EtmV4Config::commTransP0() const +{ + return (bool)((m_cfg.reg_idr0 & 0x40000000) == 0x0); +} + /* idr 1 */ inline const uint8_t EtmV4Config::MajVersion() const { @@ -424,6 +437,20 @@ inline const bool EtmV4Config::enabledVMID() const return ((m_cfg.reg_configr & (0x1 << 7)) != 0); } +inline const bool EtmV4Config::enabledVMIDOpt() const +{ + bool vmidOptVal = ((m_cfg.reg_configr & (0x1 << 15)) != 0); + /* TRIDR2.VMIDOPT[30:29] determine value used */ + if (!vmidOpt()) { /* [29] = 1'b0 */ + vmidOptVal = false; /* res0 */ + if (FullVersion() >= 0x45) { + /* umless version > 4.5 in which case [30] determines res val */ + vmidOptVal = ((m_cfg.reg_idr2 & (0x1 << 30)) != 0); + } + } + return vmidOptVal; +} + inline const EtmV4Config::CondITrace_t EtmV4Config::enabledCondITrace() { if(!m_condTraceCalc) diff --git a/contrib/opencsd/decoder/include/opencsd/etmv4/trc_etmv4_stack_elem.h b/contrib/opencsd/decoder/include/opencsd/etmv4/trc_etmv4_stack_elem.h index 5a283c541f3e..21bd7af434de 100644 --- a/contrib/opencsd/decoder/include/opencsd/etmv4/trc_etmv4_stack_elem.h +++ b/contrib/opencsd/decoder/include/opencsd/etmv4/trc_etmv4_stack_elem.h @@ -34,6 +34,7 @@ #define ARM_TRC_ETMV4_STACK_ELEM_H_INCLUDED #include "opencsd/etmv4/trc_pkt_types_etmv4.h" +#include "opencsd/trc_gen_elem_types.h" #include #include @@ -56,9 +57,16 @@ typedef enum _p0_elem_t P0_TS, P0_CC, P0_TS_CC, + P0_MARKER, P0_Q, P0_OVERFLOW, P0_FUNC_RET, + P0_SRC_ADDR, + P0_TRANS_TRACE_INIT, + P0_TRANS_START, + P0_TRANS_COMMIT, + P0_TRANS_FAIL, + P0_ITE, } p0_elem_t; @@ -101,6 +109,7 @@ class TrcStackElemAddr : public TrcStackElem { protected: TrcStackElemAddr(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index); + TrcStackElemAddr(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const bool src_addr); virtual ~TrcStackElemAddr() {}; friend class EtmV4P0Stack; @@ -120,6 +129,14 @@ inline TrcStackElemAddr::TrcStackElemAddr(const ocsd_etmv4_i_pkt_type root_pkt, m_addr_val.isa = 0; } +inline TrcStackElemAddr::TrcStackElemAddr(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const bool src_addr) : + TrcStackElem(src_addr ? P0_SRC_ADDR : P0_ADDR, false, root_pkt, root_index) +{ + m_addr_val.val = 0; + m_addr_val.isa = 0; +} + + /************************************************************/ /** Q element */ class TrcStackQElem : public TrcStackElem @@ -294,6 +311,55 @@ inline TrcStackElemParam::TrcStackElemParam(const p0_elem_t p0_type, const bool { } +/************************************************************/ +/** Marker element */ + +class TrcStackElemMarker : public TrcStackElem +{ +protected: + TrcStackElemMarker(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index); + virtual ~TrcStackElemMarker() {}; + + friend class EtmV4P0Stack; + +public: + void setMarker(const trace_marker_payload_t &marker) { m_marker = marker; }; + const trace_marker_payload_t &getMarker() const { return m_marker; }; + +private: + trace_marker_payload_t m_marker; +}; + +inline TrcStackElemMarker::TrcStackElemMarker(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) : + TrcStackElem(P0_MARKER, false, root_pkt, root_index) +{ +} + +/************************************************************/ +/* Instrumentation element + */ + +class TrcStackElemITE : public TrcStackElem +{ +protected: + TrcStackElemITE(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index); + virtual ~TrcStackElemITE() {}; + + friend class EtmV4P0Stack; + +public: + void setITE(const trace_sw_ite_t &ite) { m_ite = ite; }; + const trace_sw_ite_t &getITE() { return m_ite; }; + +private: + trace_sw_ite_t m_ite; +}; + +inline TrcStackElemITE::TrcStackElemITE(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) : + TrcStackElem(P0_ITE, false, root_pkt, root_index) +{ +} + /************************************************************/ /* P0 element stack that allows push of elements, and deletion of elements when done. */ @@ -329,6 +395,10 @@ class EtmV4P0Stack TrcStackElemCtxt *createContextElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const etmv4_context_t &context, const uint8_t IS, const bool back = false); TrcStackElemAddr *createAddrElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const etmv4_addr_val_t &addr_val); TrcStackQElem *createQElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const int count); + TrcStackElemMarker *createMarkerElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const trace_marker_payload_t &marker); + TrcStackElemAddr *createSrcAddrElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const etmv4_addr_val_t &addr_val); + TrcStackElemITE *createITEElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const trace_sw_ite_t &ite); + private: std::deque m_P0_stack; //!< P0 decode element stack std::vector m_popped_elem; //!< save list of popped but not deleted elements. diff --git a/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_decode_etmv4i.h b/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_decode_etmv4i.h index 419cd828928c..7838ece04e57 100644 --- a/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_decode_etmv4i.h +++ b/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_decode_etmv4i.h @@ -88,11 +88,29 @@ class TrcPktDecodeEtmV4I : public TrcPktDecodeBase // process Q element ocsd_err_t processQElement(); + // process a source address element + ocsd_err_t processSourceAddress(); + // process an element that cannot be cancelled / discarded ocsd_err_t processTS_CC_EventElem(TrcStackElem *pElem); + // process marker elements + ocsd_err_t processMarkerElem(TrcStackElem *pElem); + + // process a transaction element + ocsd_err_t processTransElem(TrcStackElem *pElem); + + // process an Instrumentation element + ocsd_err_t processITEElem(TrcStackElem *pElem); + // process a bad packet - ocsd_err_t handleBadPacket(const char *reason); + ocsd_err_t handleBadPacket(const char *reason, ocsd_trc_index_t index = OCSD_BAD_TRC_INDEX); + + // sequencing error on packet processing - optionally continue + ocsd_err_t handlePacketSeqErr(ocsd_err_t err, ocsd_trc_index_t index, const char *reason); + + // common packet error routine + ocsd_err_t handlePacketErr(ocsd_err_t err, ocsd_err_severity_t sev, ocsd_trc_index_t index, const char *reason); ocsd_err_t addElemCC(TrcStackElemParam *pParamElem); ocsd_err_t addElemTS(TrcStackElemParam *pParamElem, bool withCC); @@ -127,6 +145,13 @@ class TrcPktDecodeEtmV4I : public TrcPktDecodeBase ocsd_err_t returnStackPop(); // pop return stack and update instruction address. void setElemTraceRange(OcsdTraceElement &elemIn, const instr_range_t &addr_range, const bool executed, ocsd_trc_index_t index); + void setElemTraceRangeInstr(OcsdTraceElement &elemIn, const instr_range_t &addr_range, + const bool executed, ocsd_trc_index_t index, ocsd_instr_info &instr); + + // true if we are ETE configured. + inline bool isETEConfig() { + return (m_config->MajVersion() >= ETE_ARCH_VERSION); + } ocsd_mem_space_acc_t getCurrMemSpace(); @@ -134,6 +159,7 @@ class TrcPktDecodeEtmV4I : public TrcPktDecodeBase // timestamping uint64_t m_timestamp; // last broadcast global Timestamp. + bool m_ete_first_ts_marker; // state and context uint32_t m_context_id; // most recent context ID diff --git a/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4i.h b/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4i.h index 8ccf36b373db..02404749718d 100644 --- a/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4i.h +++ b/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4i.h @@ -145,7 +145,7 @@ class EtmV4ITrcPacket : public TrcPacketBase, public ocsd_etmv4_i_pkt, public t void setCondRF3(const uint16_t tokens); void setCondRF4(const uint8_t token); - void setContextInfo(const bool update, const uint8_t EL = 0, const uint8_t NS = 0, const uint8_t SF = 0); + void setContextInfo(const bool update, const uint8_t EL = 0, const uint8_t NS = 0, const uint8_t SF = 0, const uint8_t NSE = 0); void setContextVMID(const uint32_t VMID); void setContextCID(const uint32_t CID); @@ -160,6 +160,7 @@ class EtmV4ITrcPacket : public TrcPacketBase, public ocsd_etmv4_i_pkt, public t void setEvent(const uint8_t event_val); void setQType(const bool has_count, const uint32_t count, const bool has_addr, const bool addr_match, const uint8_t type); + void setITE(const uint8_t el, const uint64_t value); // packet status interface - get packet info. const ocsd_etmv4_i_pkt_type getType() const { return type; }; @@ -200,6 +201,10 @@ class EtmV4ITrcPacket : public TrcPacketBase, public ocsd_etmv4_i_pkt, public t const int getCommitElem() const { return commit_elements; }; const int getCancelElem() const { return cancel_elements; }; + // ITE + const uint8_t getITE_EL() const { return ite_pkt.el; }; + const uint64_t getITE_value() const { return ite_pkt.value; }; + // packet type const bool isBadPacket() const; @@ -207,6 +212,8 @@ class EtmV4ITrcPacket : public TrcPacketBase, public ocsd_etmv4_i_pkt, public t virtual void toString(std::string &str) const; virtual void toStringFmt(const uint32_t fmtFlags, std::string &str) const; + void setProtocolVersion(const uint8_t version) { protocol_version = version; }; + private: const char *packetTypeName(const ocsd_etmv4_i_pkt_type type, const char **pDesc) const; void contextStr(std::string &ctxtStr) const; @@ -217,6 +224,8 @@ class EtmV4ITrcPacket : public TrcPacketBase, public ocsd_etmv4_i_pkt, public t void push_vaddr(); void pop_vaddr_idx(const uint8_t idx); + const bool isETE() const { return (protocol_version & 0xF0) == 0x50; }; + Etmv4PktAddrStack m_addr_stack; }; @@ -412,7 +421,7 @@ inline void EtmV4ITrcPacket::setCondRF4(const uint8_t token) cond_result.f2f4_token = token; } -inline void EtmV4ITrcPacket::setContextInfo(const bool update, const uint8_t EL, const uint8_t NS, const uint8_t SF) +inline void EtmV4ITrcPacket::setContextInfo(const bool update, const uint8_t EL, const uint8_t NS, const uint8_t SF, const uint8_t NSE) { pkt_valid.bits.context_valid = 1; if(update) @@ -421,6 +430,7 @@ inline void EtmV4ITrcPacket::setContextInfo(const bool update, const uint8_t EL, context.EL = EL; context.NS = NS; context.SF = SF; + context.NSE = NSE; } } @@ -534,6 +544,12 @@ inline void EtmV4ITrcPacket::pop_vaddr_idx(const uint8_t idx) m_addr_stack.get_idx(idx, v_addr, v_addr_ISA); } +inline void EtmV4ITrcPacket::setITE(const uint8_t el, const uint64_t value) +{ + ite_pkt.el = el; + ite_pkt.value = value; +} + /** @}*/ #endif // ARM_TRC_PKT_ELEM_ETMV4I_H_INCLUDED diff --git a/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4i.h b/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4i.h index abc322654b8d..58c0d78806c3 100644 --- a/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4i.h +++ b/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4i.h @@ -117,6 +117,7 @@ class TrcPktProcEtmV4I : public TrcPktProcBase< EtmV4ITrcPacket, ocsd_etmv4_i_pk #define TINFO_KEY_SECT 0x02 #define TINFO_SPEC_SECT 0x04 #define TINFO_CYCT_SECT 0x08 + #define TINFO_WNDW_SECT 0x10 #define TINFO_CTRL 0x20 #define TINFO_ALL_SECT 0x1F #define TINFO_ALL 0x3F @@ -178,9 +179,10 @@ class TrcPktProcEtmV4I : public TrcPktProcBase< EtmV4ITrcPacket, ocsd_etmv4_i_pk void iPktQ(const uint8_t lastByte); void iAtom(const uint8_t lastByte); void iPktInvalidCfg(const uint8_t lastByte); // packet invalid in current config. + void iPktITE(const uint8_t lastByte); unsigned extractContField(const std::vector &buffer, const unsigned st_idx, uint32_t &value, const unsigned byte_limit = 5); - unsigned extractContField64(const std::vector &buffer, const unsigned st_idx, uint64_t &value, const unsigned byte_limit = 9); + unsigned extractTSField64(const std::vector &buffer, const unsigned st_idx, uint64_t &value); unsigned extractCondResult(const std::vector &buffer, const unsigned st_idx, uint32_t& key, uint8_t &result); void extractAndSetContextInfo(const std::vector &buffer, const int st_idx); int extract64BitLongAddr(const std::vector &buffer, const int st_idx, const uint8_t IS, uint64_t &value); diff --git a/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_types_etmv4.h b/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_types_etmv4.h index 7e98050c77c4..2a03b088c043 100644 --- a/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_types_etmv4.h +++ b/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_types_etmv4.h @@ -1,8 +1,8 @@ /* * \file trc_pkt_types_etmv4.h - * \brief OpenCSD : ETMv4 packet info + * \brief OpenCSD : ETMv4 / ETE packet info * - * \copyright Copyright (c) 2015,2019 ARM Limited. All Rights Reserved. + * \copyright Copyright (c) 2015,2019,2022 ARM Limited. All Rights Reserved. */ @@ -41,7 +41,7 @@ /** @addtogroup trc_pkts @{*/ -/** @name ETMv4 Packet Types +/** @name ETMv4 Packet Types, ETE packet Types @{*/ /** I stream packets. */ @@ -70,9 +70,12 @@ typedef enum _ocsd_etmv4_i_pkt_type ETM4_PKT_I_FUNC_RET = 0x05, /*!< b00000101 (V8M only) */ // Exceptions ETM4_PKT_I_EXCEPT = 0x06, /*!< b00000110 */ - ETM4_PKT_I_EXCEPT_RTN = 0x07, /*!< b00000111 */ + ETM4_PKT_I_EXCEPT_RTN = 0x07, /*!< b00000111 (ETE invalid) */ - /* unused encodings 0x08-0xB b00001000 to b00001011 */ + /* unused encoding 0x08 b00001000 */ + ETE_PKT_I_ITE = 0x09, /*! b00001001 (ETE only) */ + ETE_PKT_I_TRANS_ST = 0x0A, /*! b00001010 (ETE only) */ + ETE_PKT_I_TRANS_COMMIT = 0x0B, /*! b00001011 (ETE only) */ /* cycle count packets */ ETM4_PKT_I_CCNT_F2 = 0x0C, /*!< b0000110x */ @@ -91,7 +94,7 @@ typedef enum _ocsd_etmv4_i_pkt_type ETM4_PKT_I_CANCEL_F2 = 0x34, /*!< b001101xx */ ETM4_PKT_I_CANCEL_F3 = 0x38, /*!< b00111xxx */ - /* conditional instruction tracing */ + /* conditional instruction tracing - (reserved encodings ETE) */ ETM4_PKT_I_COND_I_F2 = 0x40, /*!< b01000000 - b01000010 */ ETM4_PKT_I_COND_FLUSH = 0x43, /*!< b01000011 */ ETM4_PKT_I_COND_RES_F4 = 0x44, /*!< b0100010x, b01000110 */ @@ -116,7 +119,8 @@ typedef enum _ocsd_etmv4_i_pkt_type ETM4_PKT_I_ADDR_CTXT_L_64IS0 = 0x85, /*!< b10000101 */ ETM4_PKT_I_ADDR_CTXT_L_64IS1, /*!< b10000110 */ /* unused encoding 0x87 b10000111 */ - /* unused encodings 0x88-0x8F b10001xxx */ + ETE_PKT_I_TS_MARKER = 0x88, /*!< b10001000 */ + /* unused encodings 0x89-0x8F b10001001 to b10001111 */ ETM4_PKT_I_ADDR_MATCH = 0x90, /*!< b10010000 to b10010010 0x92 */ /* unused encodings 0x93-0x94 b10010011 to b10010010 */ ETM4_PKT_I_ADDR_S_IS0 = 0x95, /*!< b10010101 */ @@ -132,7 +136,15 @@ typedef enum _ocsd_etmv4_i_pkt_type /* Q packets */ ETM4_PKT_I_Q = 0xA0, /*!< b1010xxxx */ - /* unused encodings 0xB0-0xBF b1011xxxx */ + /* ETE source address packets, unused ETMv4 */ + ETE_PKT_I_SRC_ADDR_MATCH = 0xB0, /*!< b101100xx */ + ETE_PKT_I_SRC_ADDR_S_IS0 = 0xB4, /*!< b10110100 */ + ETE_PKT_I_SRC_ADDR_S_IS1 = 0xB5, /*!< b10110101 */ + ETE_PKT_I_SRC_ADDR_L_32IS0 = 0xB6, /*!< b10110110 */ + ETE_PKT_I_SRC_ADDR_L_32IS1 = 0xB7, /*!< b10110111 */ + ETE_PKT_I_SRC_ADDR_L_64IS0 = 0xB8, /*!< b10111000 */ + ETE_PKT_I_SRC_ADDR_L_64IS1 = 0xB9, /*!< b10111001 */ + /* unused encodings 0xBA-0xBF b10111010 - b10111111 */ /* Atom packets */ ETM4_PKT_I_ATOM_F6 = 0xC0, /*!< b11000000 - b11010100 0xC0 - 0xD4, b11100000 - b11110100 0xE0 - 0xF4 */ @@ -147,15 +159,20 @@ typedef enum _ocsd_etmv4_i_pkt_type ETM4_PKT_I_DISCARD = 0x103, //!< b00000011 ETM4_PKT_I_OVERFLOW = 0x105, //!< b00000101 + // ETE extended types + ETE_PKT_I_PE_RESET = 0x400, // base type is exception packet. + ETE_PKT_I_TRANS_FAIL = 0x401, // base type is exception packet. + } ocsd_etmv4_i_pkt_type; typedef union _etmv4_trace_info_t { uint32_t val; //!< trace info full value. struct { uint32_t cc_enabled:1; //!< 1 if cycle count enabled - uint32_t cond_enabled:3; //!< conditional trace enabeld type + uint32_t cond_enabled:3; //!< conditional trace enabled type. uint32_t p0_load:1; //!< 1 if tracing with P0 load elements (for data trace) uint32_t p0_store:1; //!< 1 if tracing with P0 store elements (for data trace) + uint32_t in_trans_state:1; //!< 1 if starting trace when in a transactional state (ETE trace). } bits; //!< bitfields for trace info value. } etmv4_trace_info_t; @@ -167,6 +184,7 @@ typedef struct _etmv4_context_t { uint32_t updated:1; //!< updated this context packet (otherwise same as last time) uint32_t updated_c:1; //!< updated CtxtID uint32_t updated_v:1; //!< updated VMID + uint32_t NSE:1; //!< PE FEAT_RME: root / realm indicator }; uint32_t ctxtID; //!< Current ctxtID uint32_t VMID; //!< current VMID @@ -256,6 +274,11 @@ typedef struct _ocsd_etmv4_i_pkt }; } Q_pkt; + struct { + uint8_t el; + uint64_t value; + } ite_pkt; + //! valid bits for packet elements (addresses have their own valid bits). union { uint32_t val; @@ -277,6 +300,9 @@ typedef struct _ocsd_etmv4_i_pkt ocsd_etmv4_i_pkt_type err_type; uint8_t err_hdr_val; + // protocol version - validity of ETE specific fields 0xMm == v Major.minor + uint8_t protocol_version; + } ocsd_etmv4_i_pkt; @@ -359,6 +385,9 @@ typedef struct _ocsd_etmv4_cfg ocsd_core_profile_t core_prof; /**< Core Profile */ } ocsd_etmv4_cfg; +#define ETE_ARCH_VERSION 0x5 + +#define ETE_OPFLG_PKTDEC_SRCADDR_N_ATOMS 0x00010000 /**< Split source address output ranges for N-atoms */ /** @}*/ /** @}*/ diff --git a/contrib/opencsd/decoder/include/opencsd/ocsd_if_types.h b/contrib/opencsd/decoder/include/opencsd/ocsd_if_types.h index 23087ee694b1..f5ff6ac6c530 100644 --- a/contrib/opencsd/decoder/include/opencsd/ocsd_if_types.h +++ b/contrib/opencsd/decoder/include/opencsd/ocsd_if_types.h @@ -278,11 +278,13 @@ typedef enum _ocsd_arch_version { ARCH_V7 = 0x0700, /**< V7 architecture */ ARCH_V8 = 0x0800, /**< V8 architecture */ ARCH_V8r3 = 0x0803, /**< V8.3 architecture */ + ARCH_AA64 = 0x0864, /**< Min v8r3 plus additional AA64 PE features */ + ARCH_V8_max = ARCH_AA64, } ocsd_arch_version_t; // macros for arch version comparisons. -#define OCSD_IS_V8_ARCH(arch) ((arch >= ARCH_V8) && (arch <= ARCH_V8r3)) -#define OCSD_MIN_V8_ARCH(arch) (arch >= ARCH_V8) +#define OCSD_IS_V8_ARCH(arch) ((arch >= ARCH_V8) && (arch <= ARCH_V8_max)) +#define OCSD_IS_ARCH_MINVER(arch, min_arch) (arch >= min_arch) /** Core Profile */ typedef enum _ocsd_core_profile { @@ -336,8 +338,10 @@ typedef enum _ocsd_isa */ typedef enum _ocsd_sec_level { - ocsd_sec_secure, /**< Core is in secure state */ - ocsd_sec_nonsecure /**< Core is in non-secure state */ + ocsd_sec_secure, /**< Core is in secure state */ + ocsd_sec_nonsecure, /**< Core is in non-secure state */ + ocsd_sec_root, /**< PE FEAT_RME: Core is in root state. */ + ocsd_sec_realm, /**< PE FEAT_RME: Core is in realm state. */ } ocsd_sec_level ; /** Exception level type @@ -352,7 +356,7 @@ typedef enum _ocsd_ex_level } ocsd_ex_level; -/** instruction types - significant for waypoint calculaitons */ +/** instruction types - significant for waypoint calculations */ typedef enum _ocsd_instr_type { OCSD_INSTR_OTHER, /**< Other instruction - not significant for waypoints. */ OCSD_INSTR_BR, /**< Immediate Branch instruction */ @@ -360,6 +364,7 @@ typedef enum _ocsd_instr_type { OCSD_INSTR_ISB, /**< Barrier : ISB instruction */ OCSD_INSTR_DSB_DMB, /**< Barrier : DSB or DMB instruction */ OCSD_INSTR_WFI_WFE, /**< WFI or WFE traced as direct branch */ + OCSD_INSTR_TSTART, /**< PE Arch feature FEAT_TME - TSTART instruction */ } ocsd_instr_type; /** instruction sub types - addiitonal information passed to the output packets @@ -521,10 +526,11 @@ typedef struct _ocsd_file_mem_region { (common flags share bitfield with pkt processor common flags and create flags) @{*/ -#define OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS 0x00000100 /**< throw error on bad packets input (default is to unsync and wait) */ +#define OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS 0x00000100 /**< throw error on bad packets input (default is to warn) */ +#define OCSD_OPFLG_PKTDEC_HALT_BAD_PKTS 0x00000200 /**< halt decoder on bad packets (default is to log error and continue by resetting decoder and wait for sync */ /** mask to combine all common packet processor operational control flags */ -#define OCSD_OPFLG_PKTDEC_COMMON (OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS) +#define OCSD_OPFLG_PKTDEC_COMMON (OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS | OCSD_OPFLG_PKTDEC_HALT_BAD_PKTS) /** @}*/ @@ -547,6 +553,7 @@ typedef struct _ocsd_file_mem_region { #define OCSD_BUILTIN_DCD_ETMV4I "ETMV4I" /**< ETMv4 instruction decoder */ #define OCSD_BUILTIN_DCD_ETMV4D "ETMV4D" /**< ETMv4 data decoder */ #define OCSD_BUILTIN_DCD_PTM "PTM" /**< PTM decoder */ +#define OCSD_BUILTIN_DCD_ETE "ETE" /**< ETE decoder */ /*! Trace Protocol Builtin Types + extern */ @@ -559,6 +566,7 @@ typedef enum _ocsd_trace_protocol_t { OCSD_PROTOCOL_ETMV4D, /**< ETMV4 data trace protocol decoder. */ OCSD_PROTOCOL_PTM, /**< PTM program flow instruction trace protocol decoder. */ OCSD_PROTOCOL_STM, /**< STM system trace protocol decoder. */ + OCSD_PROTOCOL_ETE, /**< ETE trace protocol decoder */ /* others to be added here */ OCSD_PROTOCOL_BUILTIN_END, /**< Invalid protocol - built-in protocol types end marker */ @@ -627,6 +635,56 @@ typedef struct _ocsd_swt_info { /** @}*/ +/** @name Demux Statistics + + Contains statistics for the CoreSight frame demultiplexor. + + Counts total bytes sent to decoders registered against a trace ID, bytes in the input stream that are + associated with a trace ID that has no registered decoder, and frame bytes that are not trace data, but + are used to decode the frames - ID bytes, sync bytes etc. +@{*/ + +typedef struct _ocsd_demux_stats { + uint64_t valid_id_bytes; /**< number of bytes associated with an ID that has a registered decoder */ + uint64_t no_id_bytes; /**< number of bytes associated with an ID that has no decoder */ + uint64_t reserved_id_bytes; /**< number of bytes associated with reserved IDs */ + uint64_t unknown_id_bytes; /**< bytes processed before ID seen in input frames */ + uint64_t frame_bytes; /**< number of non-data bytes used for frame de-mux - ID bytes, sync etc */ +} ocsd_demux_stats_t; + +/** @}*/ + +/** @name Decode statistics + + Contains statistics for bytes decoded by the packet decoder, if statistics are supported. + + Stats block instantiated in the base class - derived protocol specific decoder must initialise and + use as required. + + The single channel block contains the stats for the requested channel via the API call. + + The global demux block contains the totals for all channels and non-data bytes used in CoreSight + frame demux. This block will show identical data for every requested channel via the API. + +@{*/ + +typedef struct _ocsd_decode_stats { + uint32_t version; /**< library version number */ + uint16_t revision; /**< revision number - defines the structure version for the stats. */ + /* single channel block */ + uint64_t channel_total; /**< total bytes processed for this channel */ + uint64_t channel_unsynced; /**< number of unsynced bytes processed on this channel */ + uint32_t bad_header_errs; /**< number of bad packet header errors */ + uint32_t bad_sequence_errs; /**< number of bad packet sequence errors */ + + ocsd_demux_stats_t demux; /**< global demux stats block */ +} ocsd_decode_stats_t; + +#define OCSD_STATS_REVISION 0x1 + +/** @}*/ + + /** @}*/ #endif // ARM_OCSD_IF_TYPES_H_INCLUDED diff --git a/contrib/opencsd/decoder/include/opencsd/ocsd_if_version.h b/contrib/opencsd/decoder/include/opencsd/ocsd_if_version.h index 38baa02e8b48..41033f0675ed 100644 --- a/contrib/opencsd/decoder/include/opencsd/ocsd_if_version.h +++ b/contrib/opencsd/decoder/include/opencsd/ocsd_if_version.h @@ -42,9 +42,9 @@ /** @name Library Versioning @{*/ -#define OCSD_VER_MAJOR 0x0 /**< Library Major Version */ -#define OCSD_VER_MINOR 0xE /**< Library Minor Version */ -#define OCSD_VER_PATCH 0x2 /**< Library Patch Version */ +#define OCSD_VER_MAJOR 0x1 /**< Library Major Version */ +#define OCSD_VER_MINOR 0x4 /**< Library Minor Version */ +#define OCSD_VER_PATCH 0x0 /**< Library Patch Version */ /** Library version number - MMMMnnpp format. MMMM = major version, @@ -53,7 +53,7 @@ */ #define OCSD_VER_NUM ((OCSD_VER_MAJOR << 16) | (OCSD_VER_MINOR << 8) | OCSD_VER_PATCH) -#define OCSD_VER_STRING "0.14.2" /**< Library Version string */ +#define OCSD_VER_STRING "1.4.0" /**< Library Version string */ #define OCSD_LIB_NAME "OpenCSD Library" /**< Library name string */ #define OCSD_LIB_SHORT_NAME "OCSD" /**< Library Short name string */ /** @}*/ diff --git a/contrib/opencsd/decoder/include/opencsd/stm/trc_pkt_proc_stm.h b/contrib/opencsd/decoder/include/opencsd/stm/trc_pkt_proc_stm.h index 909ac0cb0566..bc4391bfebfb 100644 --- a/contrib/opencsd/decoder/include/opencsd/stm/trc_pkt_proc_stm.h +++ b/contrib/opencsd/decoder/include/opencsd/stm/trc_pkt_proc_stm.h @@ -239,7 +239,8 @@ inline void TrcPktProcStm::checkSyncNibble() if((m_nibble == 0) && (m_num_F_nibbles >= 21)) { - m_is_sync = true; //this nibble marks a sync sequence - keep the F nibble count + m_is_sync = true; //this nibble marks a sync sequence + m_num_F_nibbles = 21; // set the F nibble count - lose any extra as unsynced data. } else { diff --git a/contrib/opencsd/decoder/include/opencsd/trc_gen_elem_types.h b/contrib/opencsd/decoder/include/opencsd/trc_gen_elem_types.h index 1a285a064b63..99194d118438 100644 --- a/contrib/opencsd/decoder/include/opencsd/trc_gen_elem_types.h +++ b/contrib/opencsd/decoder/include/opencsd/trc_gen_elem_types.h @@ -60,7 +60,10 @@ typedef enum _ocsd_gen_trc_elem_t OCSD_GEN_TRC_ELEM_TIMESTAMP, /*!< Timestamp - preceding elements happeded before this time. */ OCSD_GEN_TRC_ELEM_CYCLE_COUNT, /*!< Cycle count - cycles since last cycle count value - associated with a preceding instruction range. */ OCSD_GEN_TRC_ELEM_EVENT, /*!< Event - trigger or numbered event */ - OCSD_GEN_TRC_ELEM_SWTRACE, /*!< Software trace packet - may contain data payload. */ + OCSD_GEN_TRC_ELEM_SWTRACE, /*!< Software trace packet - may contain data payload. STM / ITM hardware trace with channel protocol */ + OCSD_GEN_TRC_ELEM_SYNC_MARKER, /*!< Synchronisation marker - marks position in stream of an element that is output later. */ + OCSD_GEN_TRC_ELEM_MEMTRANS, /*!< Trace indication of transactional memory operations. */ + OCSD_GEN_TRC_ELEM_INSTRUMENTATION, /*!< PE instrumentation trace - PE generated SW trace, application dependent protocol. */ OCSD_GEN_TRC_ELEM_CUSTOM, /*!< Fully custom packet type - used by none-ARM architecture decoders */ } ocsd_gen_trc_elem_t; @@ -86,6 +89,27 @@ typedef enum _unsync_info_t { UNSYNC_EOT, /**< end of trace - no additional info */ } unsync_info_t; +typedef enum _trace_sync_marker_t { + ELEM_MARKER_TS, /**< Marker for timestamp element */ +} trace_sync_marker_t; + +typedef struct _trace_marker_payload_t { + trace_sync_marker_t type; /**< type of sync marker */ + uint32_t value; /**< sync marker value - usage depends on type */ +} trace_marker_payload_t; + +typedef enum _memtrans_t { + OCSD_MEM_TRANS_TRACE_INIT,/**< Trace started while PE in transactional state */ + OCSD_MEM_TRANS_START, /**< Trace after this packet is part of a transactional memory sequence */ + OCSD_MEM_TRANS_COMMIT, /**< Transactional memory sequence valid. */ + OCSD_MEM_TRANS_FAIL, /**< Transactional memory sequence failed - operations since start of transaction have been unwound. */ +} trace_memtrans_t; + +typedef struct _sw_ite_t { + uint8_t el; /**< exception level for PE sw instrumentation instruction */ + uint64_t value; /**< payload for PE sw instrumentation instruction */ +} trace_sw_ite_t; + typedef struct _ocsd_generic_trace_elem { ocsd_gen_trc_elem_t elem_type; /**< Element type - remaining data interpreted according to this value */ ocsd_isa isa; /**< instruction set for executed instructions */ @@ -122,6 +146,9 @@ typedef struct _ocsd_generic_trace_elem { ocsd_swt_info_t sw_trace_info; /**< software trace packet info */ uint32_t num_instr_range; /**< number of instructions covered by range packet (for T32 this cannot be calculated from en-st/i_size) */ unsync_info_t unsync_eot_info; /**< additional information for unsync / end-of-trace packets. */ + trace_marker_payload_t sync_marker; /**< marker element - sync later element to position in stream */ + trace_memtrans_t mem_trans; /**< memory transaction packet - transaction event */ + trace_sw_ite_t sw_ite; /**< PE sw instrumentation using FEAT_ITE */ }; const void *ptr_extended_data; /**< pointer to extended data buffer (data trace, sw trace payload) / custom structure */ diff --git a/contrib/opencsd/decoder/source/c_api/ocsd_c_api.cpp b/contrib/opencsd/decoder/source/c_api/ocsd_c_api.cpp index 4824c427e3d1..750c847e78c8 100644 --- a/contrib/opencsd/decoder/source/c_api/ocsd_c_api.cpp +++ b/contrib/opencsd/decoder/source/c_api/ocsd_c_api.cpp @@ -234,8 +234,24 @@ OCSD_C_API ocsd_err_t ocsd_dt_attach_packet_callback( const dcd_tree_handle_t h return err; } -/*** Decode tree set element output */ +OCSD_C_API ocsd_err_t ocsd_dt_get_decode_stats(const dcd_tree_handle_t handle, + const unsigned char CSID, + ocsd_decode_stats_t **p_stats_block) +{ + DecodeTree *pDT = static_cast(handle); + + return pDT->getDecoderStats(CSID, p_stats_block); +} +OCSD_C_API ocsd_err_t ocsd_dt_reset_decode_stats(const dcd_tree_handle_t handle, + const unsigned char CSID) +{ + DecodeTree *pDT = static_cast(handle); + + return pDT->resetDecoderStats(CSID); +} + +/*** Decode tree set element output */ OCSD_C_API ocsd_err_t ocsd_dt_set_gen_elem_outfn(const dcd_tree_handle_t handle, FnTraceElemIn pFn, const void *p_context) { @@ -470,6 +486,39 @@ OCSD_C_API ocsd_err_t ocsd_dt_set_pkt_protocol_printer(const dcd_tree_handle_t h return err; } +OCSD_C_API void ocsd_err_str(const ocsd_err_t err, char *buffer, const int buffer_size) +{ + std::string err_str; + err_str = ocsdError::getErrorString(ocsdError(OCSD_ERR_SEV_ERROR, err)); + strncpy(buffer, err_str.c_str(), buffer_size - 1); + buffer[buffer_size - 1] = 0; +} + +OCSD_C_API ocsd_err_t ocsd_get_last_err(ocsd_trc_index_t *index, uint8_t *chan_id, char *message, const int message_len) +{ + ocsdError *p_err; + ocsd_err_t err = OCSD_OK; + std::string err_str; + + p_err = DecodeTree::getDefaultErrorLogger()->GetLastError(); + if (p_err) + { + *index = p_err->getErrorIndex(); + *chan_id = p_err->getErrorChanID(); + err_str = p_err->getErrorString(ocsdError(p_err)); + strncpy(message, err_str.c_str(), message_len - 1); + message[message_len - 1] = 0; + err = p_err->getErrorCode(); + } + else + { + message[0] = 0; + *index = OCSD_BAD_TRC_INDEX; + *chan_id = OCSD_BAD_CS_SRC_ID; + } + return err; +} + /*******************************************************************************/ /* C API local fns */ /*******************************************************************************/ diff --git a/contrib/opencsd/decoder/source/ete/trc_cmp_cfg_ete.cpp b/contrib/opencsd/decoder/source/ete/trc_cmp_cfg_ete.cpp new file mode 100644 index 000000000000..474cb2f7914a --- /dev/null +++ b/contrib/opencsd/decoder/source/ete/trc_cmp_cfg_ete.cpp @@ -0,0 +1,98 @@ +/* +* \file trc_cmp_cfg_ete.cpp +* \brief OpenCSD : ETE config class +* +* \copyright Copyright (c) 2019, ARM Limited. All Rights Reserved. +*/ + +/* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software without +* specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "opencsd/ete/trc_cmp_cfg_ete.h" + +ETEConfig::ETEConfig() : EtmV4Config() +{ + m_ete_cfg.reg_idr0 = 0x28000EA1; + m_ete_cfg.reg_idr1 = 0x4100FFF3; + m_ete_cfg.reg_idr2 = 0x00000488; + m_ete_cfg.reg_idr8 = 0; + m_ete_cfg.reg_configr = 0xC1; + m_ete_cfg.reg_traceidr = 0; + m_ete_cfg.arch_ver = ARCH_AA64; + m_ete_cfg.core_prof = profile_CortexA; + m_ete_cfg.reg_devarch = 0x47705A13; + copyV4(); +} + +ETEConfig::ETEConfig(const ocsd_ete_cfg *cfg_regs) : EtmV4Config() +{ + m_ete_cfg = *cfg_regs; + copyV4(); +} + +ETEConfig::~ETEConfig() +{ + +} + +//! copy assignment operator for base structure into class. +ETEConfig & ETEConfig::operator=(const ocsd_ete_cfg *p_cfg) +{ + m_ete_cfg = *p_cfg; + copyV4(); + return *this; +} + +//! cast operator returning struct const reference +//operator const ocsd_ete_cfg &() const { return m_ete_cfg; }; +//! cast operator returning struct const pointer +//operator const ocsd_ete_cfg *() const { return &m_ete_cfg; }; + +// ete superset of etmv4 - move info to underlying structure. +void ETEConfig::copyV4() +{ + // copy over 1:1 regs + m_cfg.reg_idr0 = m_ete_cfg.reg_idr0; + m_cfg.reg_idr1 = m_ete_cfg.reg_idr1; + m_cfg.reg_idr2 = m_ete_cfg.reg_idr2; + m_cfg.reg_idr8 = m_ete_cfg.reg_idr8; + m_cfg.reg_idr9 = 0; + m_cfg.reg_idr10 = 0; + m_cfg.reg_idr11 = 0; + m_cfg.reg_idr12 = 0; + m_cfg.reg_idr13 = 0; + m_cfg.reg_configr = m_ete_cfg.reg_configr; + m_cfg.reg_traceidr = m_ete_cfg.reg_traceidr; + m_cfg.core_prof = m_ete_cfg.core_prof; + m_cfg.arch_ver = m_ete_cfg.arch_ver; + + // override major / minor version as part of devarch + m_MajVer = (uint8_t)((m_ete_cfg.reg_devarch & 0xF000) >> 12); + m_MinVer = (uint8_t)((m_ete_cfg.reg_devarch & 0xF0000) >> 16); +} + +/* End of File trc_cmp_cfg_ete.cpp */ diff --git a/contrib/opencsd/decoder/source/etmv3/trc_pkt_elem_etmv3.cpp b/contrib/opencsd/decoder/source/etmv3/trc_pkt_elem_etmv3.cpp index f1e411f72423..74034c3c3e8f 100644 --- a/contrib/opencsd/decoder/source/etmv3/trc_pkt_elem_etmv3.cpp +++ b/contrib/opencsd/decoder/source/etmv3/trc_pkt_elem_etmv3.cpp @@ -659,7 +659,7 @@ void EtmV3TrcPacket::getExcepStr(std::string &excepStr) const "IRQ4", "IRQ5", "IRQ6", "IRQ7", "IRQ0","usage Fault","NMI","SVC", "DebugMonitor", "Mem Manage","PendSV","SysTick", - "Reserved","PE Reset","Reserved","HardFault" + "Reserved","PE Reset","Reserved","HardFault", "Reserved","BusFault","Reserved","Reserved" }; diff --git a/contrib/opencsd/decoder/source/etmv4/trc_cmp_cfg_etmv4.cpp b/contrib/opencsd/decoder/source/etmv4/trc_cmp_cfg_etmv4.cpp index 9f5b37396b46..6f8bf790d293 100644 --- a/contrib/opencsd/decoder/source/etmv4/trc_cmp_cfg_etmv4.cpp +++ b/contrib/opencsd/decoder/source/etmv4/trc_cmp_cfg_etmv4.cpp @@ -98,7 +98,7 @@ void EtmV4Config::CalcVMIDSize() uint32_t vmidszF = (m_cfg.reg_idr2 >> 10) & 0x1F; if(vmidszF == 1) m_VMIDSize = 8; - else if(MinVersion() > 0) + else if(FullVersion() > 0x40) { if(vmidszF == 2) m_VMIDSize = 16; diff --git a/contrib/opencsd/decoder/source/etmv4/trc_etmv4_stack_elem.cpp b/contrib/opencsd/decoder/source/etmv4/trc_etmv4_stack_elem.cpp index 8e9ba9ac43ca..a5d889413eb2 100644 --- a/contrib/opencsd/decoder/source/etmv4/trc_etmv4_stack_elem.cpp +++ b/contrib/opencsd/decoder/source/etmv4/trc_etmv4_stack_elem.cpp @@ -128,6 +128,40 @@ TrcStackQElem *EtmV4P0Stack::createQElem(const ocsd_etmv4_i_pkt_type root_pkt, c return pElem; } +TrcStackElemMarker *EtmV4P0Stack::createMarkerElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const trace_marker_payload_t &marker) +{ + TrcStackElemMarker *pElem = new (std::nothrow) TrcStackElemMarker(root_pkt, root_index); + if (pElem) + { + pElem->setMarker(marker); + push_front(pElem); + } + return pElem; +} + +TrcStackElemAddr *EtmV4P0Stack::createSrcAddrElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const etmv4_addr_val_t &addr_val) +{ + TrcStackElemAddr *pElem = new (std::nothrow) TrcStackElemAddr(root_pkt, root_index, true); + if (pElem) + { + pElem->setAddr(addr_val); + push_front(pElem); + } + return pElem; +} + +TrcStackElemITE *EtmV4P0Stack::createITEElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const trace_sw_ite_t &ite) +{ + TrcStackElemITE *pElem = new (std::nothrow) TrcStackElemITE(root_pkt, root_index); + if (pElem) + { + pElem->setITE(ite); + push_front(pElem); + } + return pElem; +} + + // iteration functions void EtmV4P0Stack::from_front_init() { @@ -150,6 +184,10 @@ void EtmV4P0Stack::erase_curr_from_front() erase_iter = m_iter; erase_iter--; m_P0_stack.erase(erase_iter); + + // explicitly delete the item here as the caller can no longer reference it. + // fixes memory leak from github issue #52 + delete *erase_iter; } diff --git a/contrib/opencsd/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp b/contrib/opencsd/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp index 393046ba23d1..89c45052868c 100644 --- a/contrib/opencsd/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp +++ b/contrib/opencsd/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp @@ -39,7 +39,8 @@ #define DCD_NAME "DCD_ETMV4" -static const uint32_t ETMV4_SUPPORTED_DECODE_OP_FLAGS = OCSD_OPFLG_PKTDEC_COMMON; +static const uint32_t ETMV4_SUPPORTED_DECODE_OP_FLAGS = OCSD_OPFLG_PKTDEC_COMMON | + ETE_OPFLG_PKTDEC_SRCADDR_N_ATOMS; TrcPktDecodeEtmV4I::TrcPktDecodeEtmV4I() : TrcPktDecodeBase(DCD_NAME) @@ -101,6 +102,14 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processPacket() m_curr_state = DECODE_PKTS; m_return_stack.flush(); } + /* ETE spec allows early event packets. */ + else if ((m_config->MajVersion() >= 0x5) && + (m_curr_packet_in->getType() == ETM4_PKT_I_EVENT)) + { + err = decodePacket(); + if (err) + resp = OCSD_RESP_FATAL_INVALID_DATA; + } bPktDone = true; break; @@ -261,6 +270,7 @@ void TrcPktDecodeEtmV4I::resetDecoder() m_out_elem.resetElemStack(); m_last_IS = 0; clearElemRes(); + m_ete_first_ts_marker = false; // elements associated with data trace #ifdef DATA_TRACE_SUPPORTED @@ -358,7 +368,25 @@ ocsd_err_t TrcPktDecodeEtmV4I::decodePacket() if (m_P0_stack.createAddrElem(m_curr_packet_in->getType(), m_index_curr_pkt, addr) == 0) bAllocErr = true; - is_addr = true; + is_addr = true; // may be waiting for target address from indirect branch + } + break; + + case ETE_PKT_I_SRC_ADDR_MATCH: + case ETE_PKT_I_SRC_ADDR_S_IS0: + case ETE_PKT_I_SRC_ADDR_S_IS1: + case ETE_PKT_I_SRC_ADDR_L_32IS0: + case ETE_PKT_I_SRC_ADDR_L_32IS1: + case ETE_PKT_I_SRC_ADDR_L_64IS0: + case ETE_PKT_I_SRC_ADDR_L_64IS1: + { + etmv4_addr_val_t addr; + + addr.val = m_curr_packet_in->getAddrVal(); + addr.isa = m_curr_packet_in->getAddrIS(); + if (m_P0_stack.createSrcAddrElem(m_curr_packet_in->getType(), m_index_curr_pkt, addr) == 0) + bAllocErr = true; + m_curr_spec_depth++; } break; @@ -438,16 +466,26 @@ ocsd_err_t TrcPktDecodeEtmV4I::decodePacket() } break; + case ETE_PKT_I_TS_MARKER: + { + trace_marker_payload_t marker; + marker.type = ELEM_MARKER_TS; + marker.value = 0; + if (m_P0_stack.createMarkerElem(m_curr_packet_in->getType(), m_index_curr_pkt, marker) == 0) + bAllocErr = true; + } + break; + case ETM4_PKT_I_BAD_SEQUENCE: - err = handleBadPacket("Bad byte sequence in packet."); + err = handleBadPacket("Bad byte sequence in packet.", m_index_curr_pkt); break; case ETM4_PKT_I_BAD_TRACEMODE: - err = handleBadPacket("Invalid packet type for trace mode."); + err = handleBadPacket("Invalid packet type for trace mode.", m_index_curr_pkt); break; case ETM4_PKT_I_RESERVED: - err = handleBadPacket("Reserved packet header"); + err = handleBadPacket("Reserved packet header", m_index_curr_pkt); break; // speculation @@ -502,8 +540,44 @@ ocsd_err_t TrcPktDecodeEtmV4I::decodePacket() } break; + /* transactional memory packets */ + case ETE_PKT_I_TRANS_ST: + { + if (m_P0_stack.createParamElemNoParam(P0_TRANS_START, m_config->commTransP0(), m_curr_packet_in->getType(), m_index_curr_pkt) == 0) + bAllocErr = true; + if (m_config->commTransP0()) + m_curr_spec_depth++; + } + break; + + case ETE_PKT_I_TRANS_COMMIT: + { + if (m_P0_stack.createParamElemNoParam(P0_TRANS_COMMIT, false, m_curr_packet_in->getType(), m_index_curr_pkt) == 0) + bAllocErr = true; + } + break; + + case ETE_PKT_I_TRANS_FAIL: + { + if (m_P0_stack.createParamElemNoParam(P0_TRANS_FAIL, false, m_curr_packet_in->getType(), m_index_curr_pkt) == 0) + bAllocErr = true; + } + break; + + /* PE Instrumentation packet */ + case ETE_PKT_I_ITE: + { + trace_sw_ite_t ite_pkt; + + ite_pkt.el = m_curr_packet_in->getITE_EL(); + ite_pkt.value = m_curr_packet_in->getITE_value(); + if (m_P0_stack.createITEElem(m_curr_packet_in->getType(), m_index_curr_pkt, ite_pkt) == 0) + bAllocErr = true; + } + break; + /*** presently unsupported packets ***/ - /* conditional instruction tracing */ + /* conditional instruction tracing */ case ETM4_PKT_I_COND_FLUSH: case ETM4_PKT_I_COND_I_F1: case ETM4_PKT_I_COND_I_F2: @@ -525,14 +599,16 @@ ocsd_err_t TrcPktDecodeEtmV4I::decodePacket() //resp = OCSD_RESP_FATAL_INVALID_DATA; #endif err = OCSD_ERR_UNSUPP_DECODE_PKT; - LogError(ocsdError(sev, err, "Data trace releated, unsupported packet type.")); + if (sev == OCSD_ERR_SEV_WARN) + LogError(ocsdError(sev, err, "Data trace related, unsupported packet type.")); + else + err = handlePacketSeqErr(err, m_index_curr_pkt, "Data trace related, unsupported packet type."); } break; default: // any other packet - bad packet error - err = OCSD_ERR_BAD_DECODE_PKT; - LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,"Unknown packet type.")); + err = handleBadPacket("Unknown packet type.", m_index_curr_pkt); break; } @@ -566,6 +642,9 @@ void TrcPktDecodeEtmV4I::doTraceInfoPacket() m_trace_info = m_curr_packet_in->getTraceInfo(); m_cc_threshold = m_curr_packet_in->getCCThreshold(); m_curr_spec_depth = m_curr_packet_in->getCurrSpecDepth(); + /* put a trans marker in stack if started in trans state */ + if (m_trace_info.bits.in_trans_state) + m_P0_stack.createParamElemNoParam(P0_TRANS_TRACE_INIT, false, m_curr_packet_in->getType(), m_index_curr_pkt); // elements associated with data trace #ifdef DATA_TRACE_SUPPORTED @@ -592,14 +671,18 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::resolveElements() if (m_elem_res.P0_commit) err = commitElements(); - if (!err && m_elem_res.P0_cancel) - err = cancelElements(); + // allow for early flush on context element + if (!m_elem_res.P0_commit) { - if (!err && m_elem_res.mispredict) - err = mispredictAtom(); - - if (!err && m_elem_res.discard) - err = discardElements(); + if (!err && m_elem_res.P0_cancel) + err = cancelElements(); + + if (!err && m_elem_res.mispredict) + err = mispredictAtom(); + + if (!err && m_elem_res.discard) + err = discardElements(); + } if (err != OCSD_OK) resp = OCSD_RESP_FATAL_INVALID_DATA; @@ -634,10 +717,11 @@ ocsd_err_t TrcPktDecodeEtmV4I::commitElements() int num_commit_req = m_elem_res.P0_commit; ocsd_trc_index_t err_idx = 0; TrcStackElem *pElem = 0; // stacked element pointer + bool contextFlush = false; err = m_out_elem.resetElemStack(); - while(m_elem_res.P0_commit && !err) + while(m_elem_res.P0_commit && !err && !contextFlush) { if (m_P0_stack.size() > 0) { @@ -646,7 +730,7 @@ ocsd_err_t TrcPktDecodeEtmV4I::commitElements() switch (pElem->getP0Type()) { - // indicates a trace restart - beginning of trace or discontinuiuty + // indicates a trace restart - beginning of trace or discontinuiuty case P0_TRC_ON: err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_TRACE_ON); if (!err) @@ -661,7 +745,7 @@ ocsd_err_t TrcPktDecodeEtmV4I::commitElements() { TrcStackElemAddr *pAddrElem = dynamic_cast(pElem); m_return_stack.clear_pop_pending(); // address removes the need to pop the indirect address target from the stack - if(pAddrElem) + if (pAddrElem) { SetInstrInfoInAddrISA(pAddrElem->getAddr().val, pAddrElem->getAddr().isa); m_need_addr = false; @@ -672,15 +756,24 @@ ocsd_err_t TrcPktDecodeEtmV4I::commitElements() case P0_CTXT: { TrcStackElemCtxt *pCtxtElem = dynamic_cast(pElem); - if(pCtxtElem) + if (pCtxtElem) { etmv4_context_t ctxt = pCtxtElem->getContext(); // check this is an updated context if(ctxt.updated) { err = m_out_elem.addElem(pElem->getRootIndex()); - if (!err) + if (!err) { updateContext(pCtxtElem, outElem()); + + // updated context - need to force this to be output to the client so correct memory + // context can be used. + contextFlush = true; + + // invalidate memory accessor cacheing - force next memory access out to client to + // ensure that the correct memory context is in play when decoding subsequent atoms. + invalidateMemAccCache(); + } } } } @@ -693,11 +786,15 @@ ocsd_err_t TrcPktDecodeEtmV4I::commitElements() err = processTS_CC_EventElem(pElem); break; + case P0_MARKER: + err = processMarkerElem(pElem); + break; + case P0_ATOM: { TrcStackElemAtom *pAtomElem = dynamic_cast(pElem); - if(pAtomElem) + if (pAtomElem) { while(!pAtomElem->isEmpty() && m_elem_res.P0_commit && !err) { @@ -709,13 +806,13 @@ ocsd_err_t TrcPktDecodeEtmV4I::commitElements() // if address and context do instruction trace follower. // otherwise skip atom and reduce committed elements - if(!m_need_ctxt && !m_need_addr) + if (!m_need_ctxt && !m_need_addr) { err = processAtom(atom); } m_elem_res.P0_commit--; // mark committed } - if(!pAtomElem->isEmpty()) + if (!pAtomElem->isEmpty()) bPopElem = false; // don't remove if still atoms to process. } } @@ -746,9 +843,27 @@ ocsd_err_t TrcPktDecodeEtmV4I::commitElements() m_elem_res.P0_commit--; break; + case P0_SRC_ADDR: + err = processSourceAddress(); + m_elem_res.P0_commit--; + break; + case P0_Q: err = processQElement(); m_elem_res.P0_commit--; + break; + + case P0_TRANS_START: + if (m_config->commTransP0()) + m_elem_res.P0_commit--; + case P0_TRANS_COMMIT: + case P0_TRANS_FAIL: + case P0_TRANS_TRACE_INIT: + err = processTransElem(pElem); + break; + + case P0_ITE: + err = processITEElem(pElem); break; } @@ -757,9 +872,8 @@ ocsd_err_t TrcPktDecodeEtmV4I::commitElements() } else { - // too few elements for commit operation - decode error. - err = OCSD_ERR_COMMIT_PKT_OVERRUN; - LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_COMMIT_PKT_OVERRUN,err_idx,m_CSID,"Not enough elements to commit")); + // too few elements for commit operation - decode error. + err = handlePacketSeqErr(OCSD_ERR_COMMIT_PKT_OVERRUN, err_idx, "Not enough elements to commit"); } } @@ -779,7 +893,7 @@ ocsd_err_t TrcPktDecodeEtmV4I::returnStackPop() if (m_return_stack.overflow()) { err = OCSD_ERR_RET_STACK_OVERFLOW; - LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, "Trace Return Stack Overflow.")); + err = handlePacketSeqErr(err, OCSD_BAD_TRC_INDEX, "Trace Return Stack Overflow."); } else { @@ -824,6 +938,25 @@ ocsd_err_t TrcPktDecodeEtmV4I::commitElemOnEOT() case P0_CTXT: break; + // trans + // P0 trans - clear and stop, otherwise skip + case P0_TRANS_START: + if (m_config->commTransP0()) + m_P0_stack.delete_all(); + break; + + // non-speculative trans fail / commit - could appear at EoT after valid trace + // but without a subsequent P0 that would force output. + case P0_TRANS_FAIL: + case P0_TRANS_COMMIT: + if (m_max_spec_depth == 0 || m_curr_spec_depth == 0) + err = processTransElem(pElem); + break; + + // others - skip non P0 + case P0_TRANS_TRACE_INIT: + break; + // output case P0_EVENT: case P0_TS: @@ -831,6 +964,14 @@ ocsd_err_t TrcPktDecodeEtmV4I::commitElemOnEOT() case P0_TS_CC: err = processTS_CC_EventElem(pElem); break; + + case P0_MARKER: + err = processMarkerElem(pElem); + break; + + case P0_ITE: + err = processITEElem(pElem); + break; } m_P0_stack.delete_back(); } @@ -886,6 +1027,8 @@ ocsd_err_t TrcPktDecodeEtmV4I::cancelElements() case P0_TS: case P0_CC: case P0_TS_CC: + case P0_MARKER: + case P0_ITE: m_P0_stack.pop_front(false); temp.push_back(pElem); break; @@ -895,6 +1038,8 @@ ocsd_err_t TrcPktDecodeEtmV4I::cancelElements() break; } } + if (m_P0_stack.size() == 0) + P0StackDone = true; } } // may have some unseen elements @@ -908,21 +1053,23 @@ ocsd_err_t TrcPktDecodeEtmV4I::cancelElements() { // too few elements for commit operation - decode error. err = OCSD_ERR_COMMIT_PKT_OVERRUN; - LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, m_index_curr_pkt, m_CSID, "Not enough elements to cancel")); + err = handlePacketSeqErr(err, m_index_curr_pkt, "Not enough elements to cancel"); m_elem_res.P0_cancel = 0; break; } - - if (temp.size()) + } + + /* restore any saved elements that are unaffected by cancel. */ + if (temp.size()) + { + while (temp.size()) { - while (temp.size()) - { - pElem = temp.back(); - m_P0_stack.push_front(pElem); - temp.pop_back(false); - } + pElem = temp.back(); + m_P0_stack.push_front(pElem); + temp.pop_back(false); } } + m_curr_spec_depth -= num_cancel_req - m_elem_res.P0_cancel; return err; } @@ -964,7 +1111,8 @@ ocsd_err_t TrcPktDecodeEtmV4I::mispredictAtom() if (!bFoundAtom && !m_unseen_spec_elem) { err = OCSD_ERR_COMMIT_PKT_OVERRUN; - LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, m_index_curr_pkt, m_CSID, "Not found mispredict atom")); + err = handlePacketSeqErr(err, m_index_curr_pkt, "Not found mispredict atom"); + //LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, m_index_curr_pkt, m_CSID, "Not found mispredict atom")); } m_elem_res.mispredict = false; return err; @@ -980,7 +1128,12 @@ ocsd_err_t TrcPktDecodeEtmV4I::discardElements() while ((m_P0_stack.size() > 0) && !err) { pElem = m_P0_stack.back(); - err = processTS_CC_EventElem(pElem); + if (pElem->getP0Type() == P0_MARKER) + err = processMarkerElem(pElem); + else if (pElem->getP0Type() == P0_MARKER) + err = processITEElem(pElem); + else + err = processTS_CC_EventElem(pElem); m_P0_stack.delete_back(); } @@ -1002,6 +1155,8 @@ ocsd_err_t TrcPktDecodeEtmV4I::discardElements() ocsd_err_t TrcPktDecodeEtmV4I::processTS_CC_EventElem(TrcStackElem *pElem) { ocsd_err_t err = OCSD_OK; + // ignore ts for ETE if not seen first TS marker on systems that use this. + bool bPermitTS = !m_config->eteHasTSMarker() || m_ete_first_ts_marker; switch (pElem->getP0Type()) { @@ -1016,7 +1171,7 @@ ocsd_err_t TrcPktDecodeEtmV4I::processTS_CC_EventElem(TrcStackElem *pElem) case P0_TS: { TrcStackElemParam *pParamElem = dynamic_cast(pElem); - if (pParamElem) + if (pParamElem && bPermitTS) err = addElemTS(pParamElem, false); } break; @@ -1032,7 +1187,7 @@ ocsd_err_t TrcPktDecodeEtmV4I::processTS_CC_EventElem(TrcStackElem *pElem) case P0_TS_CC: { TrcStackElemParam *pParamElem = dynamic_cast(pElem); - if (pParamElem) + if (pParamElem && bPermitTS) err = addElemTS(pParamElem, true); } break; @@ -1041,6 +1196,46 @@ ocsd_err_t TrcPktDecodeEtmV4I::processTS_CC_EventElem(TrcStackElem *pElem) } +ocsd_err_t TrcPktDecodeEtmV4I::processMarkerElem(TrcStackElem *pElem) +{ + ocsd_err_t err = OCSD_OK; + TrcStackElemMarker *pMarkerElem = dynamic_cast(pElem); + + if (m_config->eteHasTSMarker() && (pMarkerElem->getMarker().type == ELEM_MARKER_TS)) + m_ete_first_ts_marker = true; + + if (!err) + { + err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_SYNC_MARKER); + if (!err) + m_out_elem.getCurrElem().setSyncMarker(pMarkerElem->getMarker()); + } + return err; +} + +ocsd_err_t TrcPktDecodeEtmV4I::processTransElem(TrcStackElem *pElem) +{ + ocsd_err_t err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_MEMTRANS); + if (!err) + { + outElem().setTransactionType((trace_memtrans_t)((int)OCSD_MEM_TRANS_FAIL - + ((int)P0_TRANS_FAIL - (int)pElem->getP0Type()))); + } + return err; +} + +ocsd_err_t TrcPktDecodeEtmV4I::processITEElem(TrcStackElem *pElem) +{ + ocsd_err_t err = OCSD_OK; + TrcStackElemITE *pITEElem = dynamic_cast(pElem); + + err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_INSTRUMENTATION); + if (!err) { + outElem().setITEInfo(pITEElem->getITE()); + } + return err; +} + ocsd_err_t TrcPktDecodeEtmV4I::addElemCC(TrcStackElemParam *pParamElem) { ocsd_err_t err = OCSD_OK; @@ -1078,16 +1273,22 @@ ocsd_err_t TrcPktDecodeEtmV4I::addElemEvent(TrcStackElemParam *pParamElem) return err; } -void TrcPktDecodeEtmV4I::setElemTraceRange(OcsdTraceElement &elemIn, const instr_range_t &addr_range, - const bool executed, ocsd_trc_index_t index) +void TrcPktDecodeEtmV4I::setElemTraceRange(OcsdTraceElement &elemIn, const instr_range_t &addr_range, + const bool executed, ocsd_trc_index_t index) +{ + setElemTraceRangeInstr(elemIn, addr_range, executed, index, m_instr_info); +} + +void TrcPktDecodeEtmV4I::setElemTraceRangeInstr(OcsdTraceElement &elemIn, const instr_range_t &addr_range, + const bool executed, ocsd_trc_index_t index, ocsd_instr_info &instr) { elemIn.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE); - elemIn.setLastInstrInfo(executed, m_instr_info.type, m_instr_info.sub_type, m_instr_info.instr_size); - elemIn.setISA(m_instr_info.isa); - elemIn.setLastInstrCond(m_instr_info.is_conditional); + elemIn.setLastInstrInfo(executed, instr.type, instr.sub_type, instr.instr_size); + elemIn.setISA(instr.isa); + elemIn.setLastInstrCond(instr.is_conditional); elemIn.setAddrRange(addr_range.st_addr, addr_range.en_addr, addr_range.num_instr); if (executed) - m_instr_info.isa = m_instr_info.next_isa; + instr.isa = instr.next_isa; } ocsd_err_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom) @@ -1096,6 +1297,7 @@ ocsd_err_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom) TrcStackElem *pElem = m_P0_stack.back(); // get the atom element WP_res_t WPRes; instr_range_t addr_range; + bool ETE_ERET = false; // new element for this processed atom if ((err = m_out_elem.addElem(pElem->getRootIndex())) != OCSD_OK) @@ -1114,7 +1316,8 @@ ocsd_err_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom) } else { - LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,pElem->getRootIndex(),m_CSID,"Error processing atom packet.")); + err = handlePacketSeqErr(err, pElem->getRootIndex(), "Error processing atom packet."); + //LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,pElem->getRootIndex(),m_CSID,"Error processing atom packet.")); return err; } } @@ -1144,10 +1347,22 @@ ocsd_err_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom) if (m_instr_info.is_link) m_return_stack.push(nextAddr,m_instr_info.isa); m_return_stack.set_pop_pending(); // need to know next packet before we know what is to happen + + /* ETE does not have ERET trace packets - however to maintain the illusion if we see an ERET + output a gen elem ERET packet */ + if (isETEConfig() && (m_instr_info.sub_type == OCSD_S_INSTR_V8_ERET)) + ETE_ERET = true; } break; } setElemTraceRange(outElem(), addr_range, (atom == ATOM_E), pElem->getRootIndex()); + + if (ETE_ERET) + { + err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_EXCEPTION_RET); + if (err) + return err; + } } else { @@ -1182,55 +1397,64 @@ ocsd_err_t TrcPktDecodeEtmV4I::processException() TrcStackElemAddr *pAddressElem = 0; TrcStackElemCtxt *pCtxtElem = 0; bool branch_target = false; // exception address implies prior branch target address - ocsd_vaddr_t excep_ret_addr; + ocsd_vaddr_t excep_ret_addr = 0; ocsd_trc_index_t excep_pkt_index; WP_res_t WPRes = WP_NOT_FOUND; + bool ETE_resetPkt = false; // grab the exception element off the stack pExceptElem = dynamic_cast(m_P0_stack.back()); // get the exception element excep_pkt_index = pExceptElem->getRootIndex(); branch_target = pExceptElem->getPrevSame(); + if (pExceptElem->getRootPkt() == ETE_PKT_I_PE_RESET) + ETE_resetPkt = true; m_P0_stack.pop_back(); // remove the exception element - pElem = m_P0_stack.back(); // look at next element. - if(pElem->getP0Type() == P0_CTXT) + // ETE reset has no follow up address, the rest of the exceptions do.... + if (!ETE_resetPkt) { - pCtxtElem = dynamic_cast(pElem); - m_P0_stack.pop_back(); // remove the context element - pElem = m_P0_stack.back(); // next one should be an address element - } - - if(pElem->getP0Type() != P0_ADDR) - { - // no following address element - indicate processing error. - LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ, excep_pkt_index,m_CSID,"Address missing in exception packet.")); - return OCSD_ERR_BAD_PACKET_SEQ; - } - else - { - // extract address - pAddressElem = static_cast(pElem); - excep_ret_addr = pAddressElem->getAddr().val; - - // see if there is an address + optional context element implied - // prior to the exception. - if (branch_target) + pElem = m_P0_stack.back(); // look at next element. + if (pElem->getP0Type() == P0_CTXT) { - // this was a branch target address - update current setting - bool b64bit = m_instr_info.isa == ocsd_isa_aarch64; - if (pCtxtElem) { - b64bit = pCtxtElem->getContext().SF; - } - - // as the exception address was also a branch target address then update the - // current maintained address value. This also means that there is no range to - // output before the exception packet. - m_instr_info.instr_addr = excep_ret_addr; - m_instr_info.isa = (pAddressElem->getAddr().isa == 0) ? - (b64bit ? ocsd_isa_aarch64 : ocsd_isa_arm) : ocsd_isa_thumb2; - m_need_addr = false; + pCtxtElem = dynamic_cast(pElem); + m_P0_stack.pop_back(); // remove the context element + pElem = m_P0_stack.back(); // next one should be an address element } - } + + if (pElem->getP0Type() != P0_ADDR) + { + // no following address element - indicate processing error. + + err = handlePacketSeqErr(OCSD_ERR_BAD_PACKET_SEQ, m_index_curr_pkt, "Address missing in exception packet."); + //LogError(ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_BAD_PACKET_SEQ, excep_pkt_index, m_CSID, "Address missing in exception packet.")); + return err; + } + else + { + // extract address + pAddressElem = static_cast(pElem); + excep_ret_addr = pAddressElem->getAddr().val; + + // see if there is an address + optional context element implied + // prior to the exception. + if (branch_target) + { + // this was a branch target address - update current setting + bool b64bit = m_instr_info.isa == ocsd_isa_aarch64; + if (pCtxtElem) { + b64bit = pCtxtElem->getContext().SF; + } + + // as the exception address was also a branch target address then update the + // current maintained address value. This also means that there is no range to + // output before the exception packet. + m_instr_info.instr_addr = excep_ret_addr; + m_instr_info.isa = (pAddressElem->getAddr().isa == 0) ? + (b64bit ? ocsd_isa_aarch64 : ocsd_isa_arm) : ocsd_isa_thumb2; + m_need_addr = false; + } + } + } // need to output something - set up an element if ((err = m_out_elem.addElem(excep_pkt_index))) @@ -1246,69 +1470,72 @@ ocsd_err_t TrcPktDecodeEtmV4I::processException() return err; } - // if the preferred return address is not the end of the last output range... - if (m_instr_info.instr_addr != excep_ret_addr) - { - bool range_out = false; - instr_range_t addr_range; - - // look for match to return address. - err = traceInstrToWP(addr_range, WPRes, true, excep_ret_addr); - - if(err != OCSD_OK) + if (!ETE_resetPkt) + { + // if the preferred return address is not the end of the last output range... + if (m_instr_info.instr_addr != excep_ret_addr) { - if(err == OCSD_ERR_UNSUPPORTED_ISA) + bool range_out = false; + instr_range_t addr_range; + + // look for match to return address. + err = traceInstrToWP(addr_range, WPRes, true, excep_ret_addr); + + if (err != OCSD_OK) { - m_need_addr = true; - m_need_ctxt = true; - LogError(ocsdError(OCSD_ERR_SEV_WARN,err, excep_pkt_index,m_CSID,"Warning: unsupported instruction set processing exception packet.")); + if (err == OCSD_ERR_UNSUPPORTED_ISA) + { + m_need_addr = true; + m_need_ctxt = true; + LogError(ocsdError(OCSD_ERR_SEV_WARN, err, excep_pkt_index, m_CSID, "Warning: unsupported instruction set processing exception packet.")); + } + else + { + LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, excep_pkt_index, m_CSID, "Error processing exception packet.")); + } + return err; } - else - { - LogError(ocsdError(OCSD_ERR_SEV_ERROR,err, excep_pkt_index,m_CSID,"Error processing exception packet.")); - } - return err; - } - if(WPFound(WPRes)) - { - // waypoint address found - output range - setElemTraceRange(outElem(), addr_range, true, excep_pkt_index); - range_out = true; - } - else - { - // no waypoint - likely inaccessible memory range. - m_need_addr = true; // need an address update - - if(addr_range.st_addr != addr_range.en_addr) + if (WPFound(WPRes)) { - // some trace before we were out of memory access range + // waypoint address found - output range setElemTraceRange(outElem(), addr_range, true, excep_pkt_index); range_out = true; } + else + { + // no waypoint - likely inaccessible memory range. + m_need_addr = true; // need an address update + + if (addr_range.st_addr != addr_range.en_addr) + { + // some trace before we were out of memory access range + setElemTraceRange(outElem(), addr_range, true, excep_pkt_index); + range_out = true; + } + } + + // used the element need another for NACC or EXCEP. + if (range_out) + { + if ((err = m_out_elem.addElem(excep_pkt_index))) + return err; + } } - // used the element need another for NACC or EXCEP. - if (range_out) + // watchpoint walk resulted in inaccessible memory call... + if (WPNacc(WPRes)) { + + outElem().setType(OCSD_GEN_TRC_ELEM_ADDR_NACC); + outElem().st_addr = m_instr_info.instr_addr; + + // used the element - need another for the final exception packet. if ((err = m_out_elem.addElem(excep_pkt_index))) return err; } } - - // watchpoint walk resulted in inaccessible memory call... - if (WPNacc(WPRes)) - { - - outElem().setType(OCSD_GEN_TRC_ELEM_ADDR_NACC); - outElem().st_addr = m_instr_info.instr_addr; - // used the element - need another for the final exception packet. - if ((err = m_out_elem.addElem(excep_pkt_index))) - return err; - } - // output exception element. outElem().setType(OCSD_GEN_TRC_ELEM_EXCEPTION); @@ -1453,6 +1680,163 @@ ocsd_err_t TrcPktDecodeEtmV4I::processQElement() return err; } +ocsd_err_t TrcPktDecodeEtmV4I::processSourceAddress() +{ + ocsd_err_t err = OCSD_OK; + TrcStackElemAddr *pElem = dynamic_cast(m_P0_stack.back()); // get the address element + etmv4_addr_val_t srcAddr = pElem->getAddr(); + uint32_t opcode, bytesReq = 4; + ocsd_vaddr_t currAddr = m_instr_info.instr_addr; // get the latest decoded address. + instr_range_t out_range; + bool bSplitRangeOnN = getComponentOpMode() & ETE_OPFLG_PKTDEC_SRCADDR_N_ATOMS ? true : false; + + // check we can read instruction @ source address + err = accessMemory(srcAddr.val, getCurrMemSpace(), &bytesReq, (uint8_t *)&opcode); + if (err != OCSD_OK) + { + LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pElem->getRootIndex(), m_CSID, "Mem access error processing source address packet.")); + return err; + } + + if (bytesReq != 4) + { + // can't access - no bytes returned - output nacc. + err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_ADDR_NACC); + outElem().setAddrStart(srcAddr.val); + return err; + } + + // analyze opcode @ source address. + m_instr_info.opcode = opcode; + m_instr_info.instr_addr = srcAddr.val; + err = instrDecode(&m_instr_info); + if (err != OCSD_OK) + { + LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pElem->getRootIndex(), m_CSID, "Instruction decode error processing source address packet.")); + return err; + } + m_instr_info.instr_addr += m_instr_info.instr_size; + + // initial instruction count for the range. + out_range.num_instr = 1; + + // calculate range traced... + if (m_need_addr || (currAddr > srcAddr.val)) + { + // we were waiting for a target address, or missing trace + // that indicates how we got to the source address. + m_need_addr = false; + out_range.st_addr = srcAddr.val; + } + else + out_range.st_addr = currAddr; + out_range.en_addr = m_instr_info.instr_addr; + + // count instructions + if (out_range.en_addr - out_range.st_addr > m_instr_info.instr_size) + { + if ((m_instr_info.isa != ocsd_isa_thumb2) && !bSplitRangeOnN) + { + // all 4 byte instructions - just calculate... + out_range.num_instr = (uint32_t)(out_range.en_addr - out_range.st_addr) / 4; + } + else + { + // need to count T32 - 2 or 4 byte instructions or we are spotting N atoms + ocsd_instr_info instr; // going back to start of range so make a copy of info. + bool bMemAccErr = false; + + instr.instr_addr = out_range.st_addr; + instr.isa = m_instr_info.isa; + instr.pe_type = m_instr_info.pe_type; + instr.dsb_dmb_waypoints = m_instr_info.dsb_dmb_waypoints; + instr.wfi_wfe_branch = m_instr_info.wfi_wfe_branch; + out_range.num_instr = 0; + + while ((instr.instr_addr < out_range.en_addr) && !bMemAccErr) + { + bytesReq = 4; + err = accessMemory(instr.instr_addr, getCurrMemSpace(), &bytesReq, (uint8_t *)&opcode); + if (err != OCSD_OK) + { + LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pElem->getRootIndex(), m_CSID, "Mem access error processing source address packet.")); + return err; + } + + if (bytesReq == 4) + { + instr.opcode = opcode; + err = instrDecode(&instr); + if (err != OCSD_OK) + { + LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pElem->getRootIndex(), m_CSID, "Instruction decode error processing source address packet.")); + return err; + } + + instr.instr_addr += instr.instr_size; + out_range.num_instr++; + + /* if we are doing N atom ranges ...*/ + if (bSplitRangeOnN && (instr.instr_addr < out_range.en_addr)) + { + if (instr.type != OCSD_INSTR_OTHER) + { + instr_range_t mid_range = out_range; + mid_range.en_addr = instr.instr_addr; + + err = m_out_elem.addElem(pElem->getRootIndex()); + if (err) + return err; + setElemTraceRangeInstr(outElem(), mid_range, false, pElem->getRootIndex(), instr); + + out_range.st_addr = mid_range.en_addr; + out_range.num_instr = 0; + } + } + } + else + { + // something inaccessible between last and current... + bMemAccErr = true; + + err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_ADDR_NACC); + if (err) + return err; + outElem().setAddrStart(srcAddr.val); + + // force range to the one instruction + out_range.num_instr = 1; + out_range.st_addr = srcAddr.val; + out_range.en_addr = m_instr_info.instr_addr; // instr after the decoded instruction @ srcAddr. + } + } + } + } + + // got to the source address - output trace range, and instruction as E atom. + switch (m_instr_info.type) + { + case OCSD_INSTR_BR: + if (m_instr_info.is_link) + m_return_stack.push(m_instr_info.instr_addr, m_instr_info.isa); + m_instr_info.instr_addr = m_instr_info.branch_addr; + break; + + case OCSD_INSTR_BR_INDIRECT: + m_need_addr = true; // indirect branch taken - need new address. + if (m_instr_info.is_link) + m_return_stack.push(m_instr_info.instr_addr, m_instr_info.isa); + m_return_stack.set_pop_pending(); // need to know next packet before we know what is to happen + break; + } + m_instr_info.isa = m_instr_info.next_isa; + + // set the trace range element. + m_out_elem.addElem(pElem->getRootIndex()); + setElemTraceRange(outElem(), out_range, true, pElem->getRootIndex()); + return err; +} + void TrcPktDecodeEtmV4I::SetInstrInfoInAddrISA(const ocsd_vaddr_t addr_val, const uint8_t isa) { m_instr_info.instr_addr = addr_val; @@ -1518,7 +1902,10 @@ void TrcPktDecodeEtmV4I::updateContext(TrcStackElemCtxt *pCtxtElem, OcsdTraceEle m_is_64bit = (ctxt.SF != 0); elem.context.bits64 = ctxt.SF; m_is_secure = (ctxt.NS == 0); - elem.context.security_level = ctxt.NS ? ocsd_sec_nonsecure : ocsd_sec_secure; + if (ctxt.NSE) + elem.context.security_level = ctxt.NS ? ocsd_sec_realm : ocsd_sec_root; + else + elem.context.security_level = ctxt.NS ? ocsd_sec_nonsecure : ocsd_sec_secure; elem.context.exception_level = (ocsd_ex_level)ctxt.EL; elem.context.el_valid = 1; if(ctxt.updated_c) @@ -1537,27 +1924,42 @@ void TrcPktDecodeEtmV4I::updateContext(TrcStackElemCtxt *pCtxtElem, OcsdTraceEle m_need_ctxt = false; } -ocsd_err_t TrcPktDecodeEtmV4I::handleBadPacket(const char *reason) +ocsd_err_t TrcPktDecodeEtmV4I::handleBadPacket(const char *reason, ocsd_trc_index_t index /* = OCSD_BAD_TRC_INDEX */) { - ocsd_err_t err = OCSD_OK; + ocsd_err_severity_t sev = OCSD_ERR_SEV_WARN; + if (getComponentOpMode() & OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS) + sev = OCSD_ERR_SEV_ERROR; - if(getComponentOpMode() & OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS) + return handlePacketErr(OCSD_ERR_BAD_DECODE_PKT, sev, index, reason); +} + +ocsd_err_t TrcPktDecodeEtmV4I::handlePacketSeqErr(ocsd_err_t err, ocsd_trc_index_t index, const char *reason) +{ + return handlePacketErr(err, OCSD_ERR_SEV_ERROR, index, reason); +} + +ocsd_err_t TrcPktDecodeEtmV4I::handlePacketErr(ocsd_err_t err, ocsd_err_severity_t sev, ocsd_trc_index_t index, const char *reason) +{ + bool resetOnBadPackets = true; + + if(getComponentOpMode() & OCSD_OPFLG_PKTDEC_HALT_BAD_PKTS) + resetOnBadPackets = false; + + LogError(ocsdError(sev, err, index, getCoreSightTraceID(), reason)); + + if (resetOnBadPackets) { - // error out - stop decoding - err = OCSD_ERR_BAD_DECODE_PKT; - LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,reason)); - } - else - { - LogError(ocsdError(OCSD_ERR_SEV_WARN, OCSD_ERR_BAD_DECODE_PKT, reason)); // switch to unsync - clear decode state resetDecoder(); m_curr_state = NO_SYNC; m_unsync_eot_info = UNSYNC_BAD_PACKET; + err = OCSD_OK; } return err; + } + inline ocsd_mem_space_acc_t TrcPktDecodeEtmV4I::getCurrMemSpace() { static ocsd_mem_space_acc_t SMemSpace[] = { diff --git a/contrib/opencsd/decoder/source/etmv4/trc_pkt_elem_etmv4i.cpp b/contrib/opencsd/decoder/source/etmv4/trc_pkt_elem_etmv4i.cpp index 853fde499a1b..825b5f79e41b 100644 --- a/contrib/opencsd/decoder/source/etmv4/trc_pkt_elem_etmv4i.cpp +++ b/contrib/opencsd/decoder/source/etmv4/trc_pkt_elem_etmv4i.cpp @@ -38,6 +38,7 @@ EtmV4ITrcPacket::EtmV4ITrcPacket() { + protocol_version = 0x42; // min protocol version. } EtmV4ITrcPacket::~EtmV4ITrcPacket() @@ -101,6 +102,8 @@ void EtmV4ITrcPacket::toString(std::string &str) const contextStr(ctxtStr); case ETM4_PKT_I_ADDR_L_32IS0: case ETM4_PKT_I_ADDR_L_32IS1: + case ETE_PKT_I_SRC_ADDR_L_32IS0: + case ETE_PKT_I_SRC_ADDR_L_32IS1: trcPrintableElem::getValStr(valStr, (v_addr.size == VA_64BIT) ? 64 : 32, v_addr.valid_bits, v_addr.val, true, (v_addr.pkt_bits < 32) ? v_addr.pkt_bits : 0); str += "; Addr=" + valStr + "; " + ctxtStr; break; @@ -110,6 +113,8 @@ void EtmV4ITrcPacket::toString(std::string &str) const contextStr(ctxtStr); case ETM4_PKT_I_ADDR_L_64IS0: case ETM4_PKT_I_ADDR_L_64IS1: + case ETE_PKT_I_SRC_ADDR_L_64IS0: + case ETE_PKT_I_SRC_ADDR_L_64IS1: trcPrintableElem::getValStr(valStr, (v_addr.size == VA_64BIT) ? 64 : 32, v_addr.valid_bits, v_addr.val, true, (v_addr.pkt_bits < 64) ? v_addr.pkt_bits : 0); str += "; Addr=" + valStr + "; " + ctxtStr; break; @@ -121,11 +126,14 @@ void EtmV4ITrcPacket::toString(std::string &str) const case ETM4_PKT_I_ADDR_S_IS0: case ETM4_PKT_I_ADDR_S_IS1: + case ETE_PKT_I_SRC_ADDR_S_IS0: + case ETE_PKT_I_SRC_ADDR_S_IS1: trcPrintableElem::getValStr(valStr, (v_addr.size == VA_64BIT) ? 64 : 32, v_addr.valid_bits, v_addr.val, true, v_addr.pkt_bits); str += "; Addr=" + valStr; break; case ETM4_PKT_I_ADDR_MATCH: + case ETE_PKT_I_SRC_ADDR_MATCH: addrMatchIdx(valStr); str += ", " + valStr; trcPrintableElem::getValStr(valStr, (v_addr.size == VA_64BIT) ? 64 : 32, v_addr.valid_bits, v_addr.val, true); @@ -161,7 +169,10 @@ void EtmV4ITrcPacket::toString(std::string &str) const { std::ostringstream oss; oss << "; INFO=" << std::hex << "0x" << trace_info.val; - oss << " { CC." << std::dec << trace_info.bits.cc_enabled << " }"; + oss << " { CC." << std::dec << trace_info.bits.cc_enabled; + if (isETE()) + oss << ", TSTATE." << std::dec << trace_info.bits.in_trans_state; + oss << " }"; if (trace_info.bits.cc_enabled) oss << "; CC_THRESHOLD=" << std::hex << "0x" << cc_threshold; str += oss.str(); @@ -264,6 +275,14 @@ void EtmV4ITrcPacket::toString(std::string &str) const } } break; + + case ETE_PKT_I_ITE: + { + std::ostringstream oss; + oss << "; EL" << std::dec << (int)ite_pkt.el << "; Payload=0x" << std::hex << ite_pkt.value; + str += oss.str(); + } + break; } } @@ -349,6 +368,16 @@ const char *EtmV4ITrcPacket::packetTypeName(const ocsd_etmv4_i_pkt_type type, co pName = "I_EXCEPT_RTN"; pDesc = "Exception Return."; break; + + case ETE_PKT_I_TRANS_ST: + pName = "I_TRANS_ST"; + pDesc = "Transaction Start."; + break; + + case ETE_PKT_I_TRANS_COMMIT: + pName = "I_TRANS_COMMIT"; + pDesc = "Transaction Commit."; + break; case ETM4_PKT_I_CCNT_F1: pName = "I_CCNT_F1"; @@ -481,6 +510,11 @@ const char *EtmV4ITrcPacket::packetTypeName(const ocsd_etmv4_i_pkt_type type, co pDesc = "Address & Context, Long, 64 bit, IS1."; break; + case ETE_PKT_I_TS_MARKER: + pName = "I_TS_MARKER"; + pDesc = "Timestamp Marker"; + break; + case ETM4_PKT_I_ADDR_MATCH: pName = "I_ADDR_MATCH"; pDesc = "Exact Address Match."; @@ -521,6 +555,41 @@ const char *EtmV4ITrcPacket::packetTypeName(const ocsd_etmv4_i_pkt_type type, co pDesc = "Q Packet."; break; + case ETE_PKT_I_SRC_ADDR_MATCH: + pName = "I_SRC_ADDR_MATCH"; + pDesc = "Exact Source Address Match."; + break; + + case ETE_PKT_I_SRC_ADDR_S_IS0: + pName = "I_SRC_ADDR_S_IS0"; + pDesc = "Source Address, Short, IS0."; + break; + + case ETE_PKT_I_SRC_ADDR_S_IS1: + pName = "I_SRC_ADDR_S_IS1"; + pDesc = "Source Address, Short, IS1."; + break; + + case ETE_PKT_I_SRC_ADDR_L_32IS0: + pName = "I_SCR_ADDR_L_32IS0"; + pDesc = "Source Address, Long, 32 bit, IS0."; + break; + + case ETE_PKT_I_SRC_ADDR_L_32IS1: + pName = "I_SRC_ADDR_L_32IS1"; + pDesc = "Source Address, Long, 32 bit, IS1."; + break; + + case ETE_PKT_I_SRC_ADDR_L_64IS0: + pName = "I_SRC_ADDR_L_64IS0"; + pDesc = "Source Address, Long, 64 bit, IS0."; + break; + + case ETE_PKT_I_SRC_ADDR_L_64IS1: + pName = "I_SRC_ADDR_L_64IS1"; + pDesc = "Source Address, Long, 64 bit, IS1."; + break; + case ETM4_PKT_I_ATOM_F6: pName = "I_ATOM_F6"; pDesc = "Atom format 6."; @@ -566,6 +635,21 @@ const char *EtmV4ITrcPacket::packetTypeName(const ocsd_etmv4_i_pkt_type type, co pDesc = "Overflow."; break; + case ETE_PKT_I_PE_RESET: + pName = "I_PE_RESET"; + pDesc = "PE Reset."; + break; + + case ETE_PKT_I_TRANS_FAIL: + pName = "I_TRANS_FAIL"; + pDesc = "Transaction Fail."; + break; + + case ETE_PKT_I_ITE: + pName = "I_ITE"; + pDesc = "Instrumentation"; + break; + default: break; } diff --git a/contrib/opencsd/decoder/source/etmv4/trc_pkt_proc_etmv4i.cpp b/contrib/opencsd/decoder/source/etmv4/trc_pkt_proc_etmv4i.cpp index d8c7d84667d1..d767bdc85643 100644 --- a/contrib/opencsd/decoder/source/etmv4/trc_pkt_proc_etmv4i.cpp +++ b/contrib/opencsd/decoder/source/etmv4/trc_pkt_proc_etmv4i.cpp @@ -45,6 +45,9 @@ static const uint32_t ETMV4_SUPPORTED_OP_FLAGS = OCSD_OPFLG_PKTPROC_COMMON; +// test defines - if testing with ETMv4 sources, disable error on ERET. +// #define ETE_TRACE_ERET_AS_IGNORE + /* trace etmv4 packet processing class */ TrcPktProcEtmV4I::TrcPktProcEtmV4I() : TrcPktProcBase(ETMV4I_PKTS_NAME), m_isInit(false), @@ -70,7 +73,9 @@ ocsd_err_t TrcPktProcEtmV4I::onProtocolConfig() InitProcessorState(); m_config = *TrcPktProcBase::getProtocolConfig(); BuildIPacketTable(); // packet table based on config + m_curr_packet.setProtocolVersion(m_config.FullVersion()); m_isInit = true; + statsInit(); return OCSD_OK; } @@ -152,6 +157,10 @@ ocsd_datapath_resp_t TrcPktProcEtmV4I::processData( const ocsd_trc_index_t inde (err.getErrorCode() == OCSD_ERR_INVALID_PCKT_HDR)) { // send invalid packets up the pipe to let the next stage decide what to do. + if (err.getErrorCode() == OCSD_ERR_INVALID_PCKT_HDR) + statsAddBadHdrCount(1); + else + statsAddBadSeqCount(1); m_process_state = SEND_PKT; done = false; } @@ -171,6 +180,7 @@ ocsd_datapath_resp_t TrcPktProcEtmV4I::processData( const ocsd_trc_index_t inde } } while (!done); + statsAddTotalCount(m_trcIn.processed()); *numBytesProcessed = m_trcIn.processed(); return resp; } @@ -241,8 +251,8 @@ ocsd_datapath_resp_t TrcPktProcEtmV4I::outputUnsyncedRawPacket() { ocsd_datapath_resp_t resp = OCSD_RESP_CONT; - - outputRawPacketToMonitor(m_packet_index,&m_curr_packet,m_dump_unsynced_bytes,&m_currPacketData[0]); + statsAddUnsyncCount(m_dump_unsynced_bytes); + outputRawPacketToMonitor(m_packet_index,&m_curr_packet,m_dump_unsynced_bytes,&m_currPacketData[0]); if(!m_sent_notsync_packet) { @@ -290,6 +300,7 @@ void TrcPktProcEtmV4I::iPktNoPayload(const uint8_t lastByte) switch(m_curr_packet.type) { case ETM4_PKT_I_ADDR_MATCH: + case ETE_PKT_I_SRC_ADDR_MATCH: m_curr_packet.setAddressExactMatch(lastByte & 0x3); break; @@ -307,6 +318,8 @@ void TrcPktProcEtmV4I::iPktNoPayload(const uint8_t lastByte) case ETM4_PKT_I_EXCEPT_RTN: case ETM4_PKT_I_TRACE_ON: case ETM4_PKT_I_FUNC_RET: + case ETE_PKT_I_TRANS_ST: + case ETE_PKT_I_TRANS_COMMIT: case ETM4_PKT_I_IGNORE: default: break; } @@ -437,6 +450,8 @@ void TrcPktProcEtmV4I::iPktTraceInfo(const uint8_t lastByte) m_tinfo_sections.sectFlags |= (lastByte & 0x80) ? 0 : TINFO_SPEC_SECT; else if(!(m_tinfo_sections.sectFlags & TINFO_CYCT_SECT)) m_tinfo_sections.sectFlags |= (lastByte & 0x80) ? 0 : TINFO_CYCT_SECT; + else if (!(m_tinfo_sections.sectFlags & TINFO_WNDW_SECT)) + m_tinfo_sections.sectFlags |= (lastByte & 0x80) ? 0 : TINFO_WNDW_SECT; } // all sections accounted for? @@ -469,6 +484,11 @@ void TrcPktProcEtmV4I::iPktTraceInfo(const uint8_t lastByte) idx += extractContField(m_currPacketData,idx,fieldVal); m_curr_packet.setTraceInfoCyct(fieldVal); } + if ((presSect & TINFO_WNDW_SECT) && (idx < m_currPacketData.size())) + { + idx += extractContField(m_currPacketData, idx, fieldVal); + /* Trace commit window unsupported in current ETE versions */ + } m_process_state = SEND_PKT; m_first_trace_info = true; } @@ -502,8 +522,11 @@ void TrcPktProcEtmV4I::iPktTimestamp(const uint8_t lastByte) { int idx = 1; uint64_t tsVal; - int ts_bytes = extractContField64(m_currPacketData, idx, tsVal); - int ts_bits = ts_bytes < 7 ? ts_bytes * 7 : 64; + int ts_bytes = extractTSField64(m_currPacketData, idx, tsVal); + int ts_bits; + + // if ts_bytes 8 or less, then cont bits on each byte, otherwise full 64 bit value for 9 bytes + ts_bits = ts_bytes < 9 ? ts_bytes * 7 : 64; if(!m_curr_packet.pkt_valid.bits.ts_valid && m_first_trace_info) ts_bits = 64; // after trace info, missing bits are all 0. @@ -534,6 +557,13 @@ void TrcPktProcEtmV4I::iPktException(const uint8_t lastByte) case 1: m_excep_size = 3; break; case 2: if((lastByte & 0x80) == 0x00) m_excep_size = 2; + // ETE exception reset or trans failed + if (m_config.MajVersion() >= 0x5) + { + excep_type = (m_currPacketData[1] >> 1) & 0x1F; + if ((excep_type == 0x0) || (excep_type == 0x18)) + m_excep_size = 3; + } break; } @@ -553,6 +583,18 @@ void TrcPktProcEtmV4I::iPktException(const uint8_t lastByte) m_curr_packet.setExceptionInfo(excep_type,addr_interp,m_fault_pending, m_type); m_process_state = SEND_PKT; + // ETE exception reset or trans failed + if (m_config.MajVersion() >= 0x5) + { + if ((excep_type == 0x0) || (excep_type == 0x18)) + { + m_curr_packet.set64BitAddress(0, 0); + if (excep_type == 0x18) + m_curr_packet.setType(ETE_PKT_I_TRANS_FAIL); + else + m_curr_packet.setType(ETE_PKT_I_PE_RESET); + } + } // allow the standard address packet handlers to process the address packet field for the exception. } } @@ -833,7 +875,7 @@ void TrcPktProcEtmV4I::extractAndSetContextInfo(const std::vector &buff // on input, buffer index points at the info byte - always present uint8_t infoByte = m_currPacketData[st_idx]; - m_curr_packet.setContextInfo(true, (infoByte & 0x3), (infoByte >> 5) & 0x1, (infoByte >> 4) & 0x1); + m_curr_packet.setContextInfo(true, (infoByte & 0x3), (infoByte >> 5) & 0x1, (infoByte >> 4) & 0x1, (infoByte >> 3) & 0x1); // see if there are VMID and CID bytes, and how many. int nVMID_bytes = ((infoByte & 0x40) == 0x40) ? (m_config.vmidSize()/8) : 0; @@ -937,7 +979,8 @@ void TrcPktProcEtmV4I::iPktShortAddr(const uint8_t lastByte) { m_addr_done = false; m_addrIS = 0; - if (lastByte == ETM4_PKT_I_ADDR_S_IS1) + if ((lastByte == ETM4_PKT_I_ADDR_S_IS1) || + (lastByte == ETE_PKT_I_SRC_ADDR_S_IS1)) m_addrIS = 1; } else if(!m_addr_done) @@ -988,14 +1031,18 @@ void TrcPktProcEtmV4I::iPktLongAddr(const uint8_t lastByte) switch(m_curr_packet.type) { case ETM4_PKT_I_ADDR_L_32IS1: + case ETE_PKT_I_SRC_ADDR_L_32IS1: m_addrIS = 1; case ETM4_PKT_I_ADDR_L_32IS0: + case ETE_PKT_I_SRC_ADDR_L_32IS0: m_addrBytes = 4; break; case ETM4_PKT_I_ADDR_L_64IS1: + case ETE_PKT_I_SRC_ADDR_L_64IS1: m_addrIS = 1; case ETM4_PKT_I_ADDR_L_64IS0: + case ETE_PKT_I_SRC_ADDR_L_64IS0: m_addrBytes = 8; m_bAddr64bit = true; break; @@ -1203,6 +1250,23 @@ void TrcPktProcEtmV4I::iAtom(const uint8_t lastByte) m_process_state = SEND_PKT; } +void TrcPktProcEtmV4I::iPktITE(const uint8_t /* lastByte */) +{ + uint64_t value; + int shift = 0; + + /* packet is always 10 bytes, Header, EL info byte, 8 bytes payload */ + if (m_currPacketData.size() == 10) { + value = 0; + for (int i = 2; i < 10; i++) { + value |= ((uint64_t)m_currPacketData[i]) << shift; + shift += 8; + } + m_curr_packet.setITE(m_currPacketData[1], value); + m_process_state = SEND_PKT; + } +} + // header byte processing is table driven. void TrcPktProcEtmV4I::BuildIPacketTable() { @@ -1247,7 +1311,35 @@ void TrcPktProcEtmV4I::BuildIPacketTable() // b0000 0111 - exception return m_i_table[0x07].pkt_type = ETM4_PKT_I_EXCEPT_RTN; - m_i_table[0x07].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload; + if (m_config.MajVersion() >= 0x5) // not valid for ETE + { +#ifdef ETE_TRACE_ERET_AS_IGNORE + m_i_table[0x07].pkt_type = ETM4_PKT_I_IGNORE; + m_i_table[0x07].pptkFn = &EtmV4IPktProcImpl::iPktNoPayload; +#else + m_i_table[0x07].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg; +#endif + } + else + m_i_table[0x07].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload; + + // b00001010, b00001011 ETE TRANS packets + // b00001001 - ETE sw instrumentation packet + if (m_config.MajVersion() >= 0x5) + { + m_i_table[0x0A].pkt_type = ETE_PKT_I_TRANS_ST; + m_i_table[0x0A].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload; + + m_i_table[0x0B].pkt_type = ETE_PKT_I_TRANS_COMMIT; + m_i_table[0x0B].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload; + + // FEAT_ITE - sw instrumentation packet + if (m_config.MinVersion() >= 0x3) + { + m_i_table[0x09].pkt_type = ETE_PKT_I_ITE; + m_i_table[0x09].pptkFn = &TrcPktProcEtmV4I::iPktITE; + } + } // b0000 110x - cycle count f2 // b0000 111x - cycle count f1 @@ -1443,6 +1535,12 @@ void TrcPktProcEtmV4I::BuildIPacketTable() m_i_table[0x85+i].pptkFn = &TrcPktProcEtmV4I::iPktAddrCtxt; } + // 0b1000 1000 - ETE 1.1 TS Marker. also ETMv4.6 + if(m_config.FullVersion() >= 0x46) + { + m_i_table[0x88].pkt_type = ETE_PKT_I_TS_MARKER; + m_i_table[0x88].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload; + } // 0b1001 0000 to b1001 0010 - exact match addr for(int i = 0; i < 3; i++) { @@ -1492,6 +1590,30 @@ void TrcPktProcEtmV4I::BuildIPacketTable() } } + // b10110000 - b10111001 - ETE src address packets + if (m_config.FullVersion() >= 0x50) + { + for (int i = 0; i < 3; i++) + { + m_i_table[0xB0 + i].pkt_type = ETE_PKT_I_SRC_ADDR_MATCH; + m_i_table[0xB0 + i].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload; + } + + m_i_table[0xB4].pkt_type = ETE_PKT_I_SRC_ADDR_S_IS0; + m_i_table[0xB4].pptkFn = &TrcPktProcEtmV4I::iPktShortAddr; + m_i_table[0xB5].pkt_type = ETE_PKT_I_SRC_ADDR_S_IS1; + m_i_table[0xB5].pptkFn = &TrcPktProcEtmV4I::iPktShortAddr; + + m_i_table[0xB6].pkt_type = ETE_PKT_I_SRC_ADDR_L_32IS0; + m_i_table[0xB6].pptkFn = &TrcPktProcEtmV4I::iPktLongAddr; + m_i_table[0xB7].pkt_type = ETE_PKT_I_SRC_ADDR_L_32IS1; + m_i_table[0xB7].pptkFn = &TrcPktProcEtmV4I::iPktLongAddr; + m_i_table[0xB8].pkt_type = ETE_PKT_I_SRC_ADDR_L_64IS0; + m_i_table[0xB8].pptkFn = &TrcPktProcEtmV4I::iPktLongAddr; + m_i_table[0xB9].pkt_type = ETE_PKT_I_SRC_ADDR_L_64IS1; + m_i_table[0xB9].pptkFn = &TrcPktProcEtmV4I::iPktLongAddr; + } + // Atom Packets - all no payload but have specific pattern generation fn for(int i = 0xC0; i <= 0xD4; i++) // atom f6 { @@ -1559,20 +1681,33 @@ void TrcPktProcEtmV4I::BuildIPacketTable() return idx; } -unsigned TrcPktProcEtmV4I::extractContField64(const std::vector &buffer, const unsigned st_idx, uint64_t &value, const unsigned byte_limit /*= 9*/) +unsigned TrcPktProcEtmV4I::extractTSField64(const std::vector &buffer, const unsigned st_idx, uint64_t &value) { + const unsigned max_byte_idx = 8; /* the 9th byte, index 8, will use full 8 bits for value */ unsigned idx = 0; bool lastByte = false; uint8_t byteVal; + uint8_t byteValMask = 0x7f; + + /* init value */ value = 0; - while(!lastByte && (idx < byte_limit)) // max 9 bytes for 64 bit value; + while(!lastByte) // max 9 bytes for 64 bit value; { if(buffer.size() > (st_idx + idx)) { // each byte has seven bits + cont bit byteVal = buffer[(st_idx + idx)]; - lastByte = (byteVal & 0x80) != 0x80; - value |= ((uint64_t)(byteVal & 0x7F)) << (idx * 7); + + /* detect the final byte - which uses full 8 bits as value */ + if (idx == max_byte_idx) + { + byteValMask = 0xFF; /* last byte of 9, no cont bit */ + lastByte = true; + } + else + lastByte = (byteVal & 0x80) != 0x80; + + value |= ((uint64_t)(byteVal & byteValMask)) << (idx * 7); idx++; } else @@ -1580,6 +1715,7 @@ unsigned TrcPktProcEtmV4I::extractContField64(const std::vector &buffer throwBadSequenceError("Invalid 64 bit continuation fields in packet"); } } + // index is the count of bytes used here. return idx; } diff --git a/contrib/opencsd/decoder/source/i_dec/trc_i_decode.cpp b/contrib/opencsd/decoder/source/i_dec/trc_i_decode.cpp index 614fc1d8b45c..0e0589512002 100644 --- a/contrib/opencsd/decoder/source/i_dec/trc_i_decode.cpp +++ b/contrib/opencsd/decoder/source/i_dec/trc_i_decode.cpp @@ -42,7 +42,7 @@ ocsd_err_t TrcIDecode::DecodeInstruction(ocsd_instr_info *instr_info) struct decode_info info; info.instr_sub_type = OCSD_S_INSTR_NONE; - info.arch_version = (uint16_t)(instr_info->pe_type.arch); + info.arch_version = instr_info->pe_type.arch; switch(instr_info->isa) { @@ -136,14 +136,12 @@ ocsd_err_t TrcIDecode::DecodeA64(ocsd_instr_info *instr_info, struct decode_info if(inst_A64_is_indirect_branch_link(instr_info->opcode, &instr_info->is_link, info)) { instr_info->type = OCSD_INSTR_BR_INDIRECT; -// instr_info->is_link = inst_A64_is_branch_and_link(instr_info->opcode); } else if(inst_A64_is_direct_branch_link(instr_info->opcode, &instr_info->is_link, info)) { inst_A64_branch_destination(instr_info->instr_addr,instr_info->opcode,&branchAddr); instr_info->type = OCSD_INSTR_BR; instr_info->branch_addr = (ocsd_vaddr_t)branchAddr; -// instr_info->is_link = inst_A64_is_branch_and_link(instr_info->opcode); } else if((barrier = inst_A64_barrier(instr_info->opcode)) != ARM_BARRIER_NONE) { @@ -160,12 +158,15 @@ ocsd_err_t TrcIDecode::DecodeA64(ocsd_instr_info *instr_info, struct decode_info break; } } - else if (instr_info->wfi_wfe_branch) + else if (instr_info->wfi_wfe_branch && + inst_A64_wfiwfe(instr_info->opcode, info)) { - if (inst_A64_wfiwfe(instr_info->opcode)) - { - instr_info->type = OCSD_INSTR_WFI_WFE; - } + instr_info->type = OCSD_INSTR_WFI_WFE; + } + else if (OCSD_IS_ARCH_MINVER(info->arch_version, ARCH_AA64)) + { + if (inst_A64_Tstart(instr_info->opcode)) + instr_info->type = OCSD_INSTR_TSTART; } instr_info->is_conditional = inst_A64_is_conditional(instr_info->opcode); diff --git a/contrib/opencsd/decoder/source/i_dec/trc_idec_arminst.cpp b/contrib/opencsd/decoder/source/i_dec/trc_idec_arminst.cpp index 3652e84921f3..76951fd38183 100644 --- a/contrib/opencsd/decoder/source/i_dec/trc_idec_arminst.cpp +++ b/contrib/opencsd/decoder/source/i_dec/trc_idec_arminst.cpp @@ -244,8 +244,9 @@ int inst_A64_is_direct_branch_link(uint32_t inst, uint8_t *is_link, struct decod int is_direct_branch = 1; if ((inst & 0x7c000000) == 0x34000000) { /* CB, TB */ - } else if ((inst & 0xff000010) == 0x54000000) { + } else if ((inst & 0xff000000) == 0x54000000) { /* B */ + /* BC 8.8 / 9.3 arch - bit 4 = 1'b1 */ } else if ((inst & 0x7c000000) == 0x14000000) { /* B, BL imm */ if (inst & 0x80000000) { @@ -258,11 +259,26 @@ int inst_A64_is_direct_branch_link(uint32_t inst, uint8_t *is_link, struct decod return is_direct_branch; } -int inst_A64_wfiwfe(uint32_t inst) +int inst_A64_wfiwfe(uint32_t inst, struct decode_info *info) { /* WFI, WFE may be traced as branches in etm 4.3++ */ if ((inst & 0xffffffdf) == 0xd503205f) return 1; + + /* new feature introduced post v8.3 */ + if (OCSD_IS_ARCH_MINVER(info->arch_version, ARCH_AA64)) + { + /* WFIT / WFET for later archs */ + if ((inst & 0xffffffc0) == 0xd5031000) + return 1; + } + return 0; +} + +int inst_A64_Tstart(uint32_t inst) +{ + if ((inst & 0xffffffe0) == 0xd5233060) + return 1; return 0; } @@ -288,7 +304,7 @@ int inst_A64_is_indirect_branch_link(uint32_t inst, uint8_t *is_link, struct dec } else if ((inst & 0xffffffff) == 0xd69f03e0) { /* ERET */ info->instr_sub_type = OCSD_S_INSTR_V8_ERET; - } else if (info->arch_version >= 0x0803) { + } else if (OCSD_IS_ARCH_MINVER(info->arch_version, ARCH_V8r3)) { /* new pointer auth instr for v8.3 arch */ if ((inst & 0xffdff800) == 0xd71f0800) { /* BRAA, BRAB, BLRAA, BLRBB */ @@ -399,8 +415,9 @@ int inst_A64_branch_destination(uint64_t addr, uint32_t inst, uint64_t *pnpc) { uint64_t npc; int is_direct_branch = 1; - if ((inst & 0xff000010) == 0x54000000) { + if ((inst & 0xff000000) == 0x54000000) { /* B */ + /* BC */ npc = addr + ((int32_t)((inst & 0x00ffffe0) << 8) >> 11); } else if ((inst & 0x7c000000) == 0x14000000) { /* B, BL imm */ @@ -484,7 +501,7 @@ int inst_A64_is_branch_and_link(uint32_t inst, struct decode_info *info) } else if ((inst & 0xfc000000) == 0x94000000) { /* BL */ info->instr_sub_type = OCSD_S_INSTR_BR_LINK; - } else if (info->arch_version >= 0x0803) { + } else if (OCSD_IS_ARCH_MINVER(info->arch_version, ARCH_V8r3)) { /* new pointer auth instr for v8.3 arch */ if ((inst & 0xfffff800) == 0xd73f0800) { /* BLRAA, BLRBB */ @@ -553,8 +570,9 @@ int inst_A64_is_conditional(uint32_t inst) if ((inst & 0x7c000000) == 0x34000000) { /* CB, TB */ return 1; - } else if ((inst & 0xff000010) == 0x54000000) { + } else if ((inst & 0xff000000) == 0x54000000) { /* B.cond */ + /* BC.cond */ return 1; } return 0; diff --git a/contrib/opencsd/decoder/source/mem_acc/trc_mem_acc_mapper.cpp b/contrib/opencsd/decoder/source/mem_acc/trc_mem_acc_mapper.cpp index 53edfe1a1616..dc07a1ed5a25 100644 --- a/contrib/opencsd/decoder/source/mem_acc/trc_mem_acc_mapper.cpp +++ b/contrib/opencsd/decoder/source/mem_acc/trc_mem_acc_mapper.cpp @@ -119,6 +119,14 @@ ocsd_err_t TrcMemAccMapper::ReadTargetMemory(const ocsd_vaddr_t address, const u return err; } +void TrcMemAccMapper::InvalidateMemAccCache(const uint8_t /* cs_trace_id */) +{ + // default mapper does not use cs_trace_id for cache invalidation. + if (m_cache.enabled()) + m_cache.invalidateAll(); + m_acc_curr = 0; +} + void TrcMemAccMapper::RemoveAllAccessors() { TrcMemAccessorBase *pAcc = 0; diff --git a/contrib/opencsd/decoder/source/ocsd_dcd_tree.cpp b/contrib/opencsd/decoder/source/ocsd_dcd_tree.cpp index be15e36e9cb3..8e29269d1690 100644 --- a/contrib/opencsd/decoder/source/ocsd_dcd_tree.cpp +++ b/contrib/opencsd/decoder/source/ocsd_dcd_tree.cpp @@ -101,6 +101,13 @@ DecodeTree::DecodeTree() : { for(int i = 0; i < 0x80; i++) m_decode_elements[i] = 0; + + // reset the global demux stats. + m_demux_stats.frame_bytes = 0; + m_demux_stats.no_id_bytes = 0; + m_demux_stats.valid_id_bytes = 0; + m_demux_stats.unknown_id_bytes = 0; + m_demux_stats.reserved_id_bytes = 0; } DecodeTree::~DecodeTree() @@ -486,6 +493,62 @@ ocsd_err_t DecodeTree::removeDecoder(const uint8_t CSID) return err; } +ocsd_err_t DecodeTree::getDecoderStats(const uint8_t CSID, ocsd_decode_stats_t **p_stats_block) +{ + ocsd_err_t err = OCSD_OK; + TrcPktProcI *pPktProc = getPktProcI(CSID); + if (!pPktProc) + return OCSD_ERR_INVALID_PARAM_VAL; + err = pPktProc->getStatsBlock(p_stats_block); + if (err == OCSD_OK) { + // copy in the global demux stats. + (*p_stats_block)->demux.frame_bytes = m_demux_stats.frame_bytes; + (*p_stats_block)->demux.no_id_bytes = m_demux_stats.no_id_bytes; + (*p_stats_block)->demux.valid_id_bytes = m_demux_stats.valid_id_bytes; + (*p_stats_block)->demux.unknown_id_bytes = m_demux_stats.unknown_id_bytes; + (*p_stats_block)->demux.reserved_id_bytes = m_demux_stats.reserved_id_bytes; + } + return err; +} + +ocsd_err_t DecodeTree::resetDecoderStats(const uint8_t CSID) +{ + TrcPktProcI *pPktProc = getPktProcI(CSID); + if (!pPktProc) + return OCSD_ERR_INVALID_PARAM_VAL; + pPktProc->resetStats(); + + // reset the global demux stats. + m_demux_stats.frame_bytes = 0; + m_demux_stats.no_id_bytes = 0; + m_demux_stats.valid_id_bytes = 0; + m_demux_stats.unknown_id_bytes = 0; + m_demux_stats.reserved_id_bytes = 0; + return OCSD_OK; +} + +TrcPktProcI *DecodeTree::getPktProcI(const uint8_t CSID) +{ + TrcPktProcI *pPktProc = 0; + TraceComponent *pComp, *pAssoc; + DecodeTreeElement *pElem = getDecoderElement(CSID); + + if (pElem) + { + pComp = pElem->getDecoderHandle(); + if (pComp) + { + /* if this is a full decoder then the associated component is the packet processor */ + pAssoc = pComp->getAssocComponent(); + if (pAssoc) + pPktProc = dynamic_cast(pAssoc); + else + pPktProc = dynamic_cast(pComp); + } + } + return pPktProc; +} + DecodeTreeElement * DecodeTree::getDecoderElement(const uint8_t CSID) const { DecodeTreeElement *ret_elem = 0; @@ -511,7 +574,7 @@ DecodeTreeElement *DecodeTree::getNextElement(uint8_t &elemID) if(m_decode_elem_iter < 0x80) { // find a none zero entry or end of range - while((m_decode_elements[m_decode_elem_iter] == 0) && (m_decode_elem_iter < 0x80)) + while((m_decode_elem_iter < 0x80) && (m_decode_elements[m_decode_elem_iter] == 0)) m_decode_elem_iter++; // return entry unless end of range @@ -527,7 +590,7 @@ DecodeTreeElement *DecodeTree::getNextElement(uint8_t &elemID) bool DecodeTree::initialise(const ocsd_dcd_tree_src_t type, uint32_t formatterCfgFlags) { - bool initOK = true; + ocsd_err_t err; m_dcd_tree_type = type; if(type == OCSD_TRC_SRC_FRAME_FORMATTED) { @@ -535,14 +598,19 @@ bool DecodeTree::initialise(const ocsd_dcd_tree_src_t type, uint32_t formatterCf m_frame_deformatter_root = new (std::nothrow) TraceFormatterFrameDecoder(); if(m_frame_deformatter_root) { - m_frame_deformatter_root->Configure(formatterCfgFlags); + if (m_frame_deformatter_root->Init() != OCSD_OK) + return false; m_frame_deformatter_root->getErrLogAttachPt()->attach(DecodeTree::s_i_error_logger); + err = m_frame_deformatter_root->Configure(formatterCfgFlags); + if (err != OCSD_OK) + return false; m_i_decoder_root = dynamic_cast(m_frame_deformatter_root); + m_frame_deformatter_root->SetDemuxStatsBlock(&m_demux_stats); } else - initOK = false; + return false; } - return initOK; + return true; } void DecodeTree::setSingleRoot(TrcPktProcI *pComp) @@ -621,6 +689,7 @@ ocsd_err_t DecodeTree::addPacketPrinter(uint8_t CSID, bool bMonitor, ItemPrinter switch (protocol) { case OCSD_PROTOCOL_ETMV4I: + case OCSD_PROTOCOL_ETE: { PacketPrinter *pTPrinter = dynamic_cast *>(pPrinter); if (bMonitor) diff --git a/contrib/opencsd/decoder/source/ocsd_error.cpp b/contrib/opencsd/decoder/source/ocsd_error.cpp index 74e9e4977f60..ee01064a3476 100644 --- a/contrib/opencsd/decoder/source/ocsd_error.cpp +++ b/contrib/opencsd/decoder/source/ocsd_error.cpp @@ -229,4 +229,25 @@ void ocsdError::appendErrorDetails(std::string &errStr, const ocsdError &error) errStr = oss.str(); } + +const char* ocsdDataRespStr::getStr() +{ + static const char* szRespStr[] = { + "OCSD_RESP_CONT: Continue processing.", + "OCSD_RESP_WARN_CONT: Continue processing -> a component logged a warning.", + "OCSD_RESP_ERR_CONT: Continue processing -> a component logged an error.", + "OCSD_RESP_WAIT: Pause processing", + "OCSD_RESP_WARN_WAIT: Pause processing -> a component logged a warning.", + "OCSD_RESP_ERR_WAIT: Pause processing -> a component logged an error.", + "OCSD_RESP_FATAL_NOT_INIT: Processing Fatal Error : component unintialised.", + "OCSD_RESP_FATAL_INVALID_OP: Processing Fatal Error : invalid data path operation.", + "OCSD_RESP_FATAL_INVALID_PARAM: Processing Fatal Error : invalid parameter in datapath call.", + "OCSD_RESP_FATAL_INVALID_DATA: Processing Fatal Error : invalid trace data.", + "OCSD_RESP_FATAL_SYS_ERR: Processing Fatal Error : internal system error." + }; + if ((m_type < OCSD_RESP_CONT) || (m_type > OCSD_RESP_FATAL_SYS_ERR)) + return "Unknown OCSD_RESP type."; + return szRespStr[m_type]; +} + /* End of File ocsd_error.cpp */ diff --git a/contrib/opencsd/decoder/source/ocsd_gen_elem_stack.cpp b/contrib/opencsd/decoder/source/ocsd_gen_elem_stack.cpp index bb758427a9b8..66fe75d9899a 100644 --- a/contrib/opencsd/decoder/source/ocsd_gen_elem_stack.cpp +++ b/contrib/opencsd/decoder/source/ocsd_gen_elem_stack.cpp @@ -42,6 +42,7 @@ OcsdGenElemStack::OcsdGenElemStack() : m_curr_elem_idx(0), m_send_elem_idx(0), m_CSID(0), + m_sendIf(NULL), m_is_init(false) { diff --git a/contrib/opencsd/decoder/source/ocsd_lib_dcd_register.cpp b/contrib/opencsd/decoder/source/ocsd_lib_dcd_register.cpp index adb042dcadff..0233c89eaa06 100644 --- a/contrib/opencsd/decoder/source/ocsd_lib_dcd_register.cpp +++ b/contrib/opencsd/decoder/source/ocsd_lib_dcd_register.cpp @@ -39,13 +39,15 @@ #include "opencsd/etmv3/trc_dcd_mngr_etmv3.h" #include "opencsd/ptm/trc_dcd_mngr_ptm.h" #include "opencsd/stm/trc_dcd_mngr_stm.h" +#include "opencsd/ete/trc_dcd_mngr_ete.h" // create array of built-in decoders to register with library static built_in_decoder_info_t sBuiltInArray[] = { CREATE_BUILTIN_ENTRY(DecoderMngrEtmV4I,OCSD_BUILTIN_DCD_ETMV4I), CREATE_BUILTIN_ENTRY(DecoderMngrEtmV3, OCSD_BUILTIN_DCD_ETMV3), CREATE_BUILTIN_ENTRY(DecoderMngrPtm, OCSD_BUILTIN_DCD_PTM), - CREATE_BUILTIN_ENTRY(DecoderMngrStm, OCSD_BUILTIN_DCD_STM) + CREATE_BUILTIN_ENTRY(DecoderMngrStm, OCSD_BUILTIN_DCD_STM), + CREATE_BUILTIN_ENTRY(DecoderMngrETE, OCSD_BUILTIN_DCD_ETE) //{ 0, 0, 0} }; @@ -90,7 +92,6 @@ OcsdLibDcdRegister::~OcsdLibDcdRegister() m_pLastTypedDecoderMngr = 0; } - const ocsd_err_t OcsdLibDcdRegister::registerDecoderTypeByName(const std::string &name, IDecoderMngr *p_decoder_fact) { if(isRegisteredDecoder(name)) diff --git a/contrib/opencsd/decoder/source/pkt_printers/trc_print_fact.cpp b/contrib/opencsd/decoder/source/pkt_printers/trc_print_fact.cpp index 52dcb6b3e1ac..6b5df1f472e0 100644 --- a/contrib/opencsd/decoder/source/pkt_printers/trc_print_fact.cpp +++ b/contrib/opencsd/decoder/source/pkt_printers/trc_print_fact.cpp @@ -55,8 +55,9 @@ ItemPrinter *PktPrinterFact::createProtocolPrinter(std::vector &p { ItemPrinter *pPrinter = 0; switch (protocol) - { + { case OCSD_PROTOCOL_ETMV4I: + case OCSD_PROTOCOL_ETE: pPrinter = new (std::nothrow) PacketPrinter(CSID); break; case OCSD_PROTOCOL_ETMV3: diff --git a/contrib/opencsd/decoder/source/ptm/trc_pkt_proc_ptm.cpp b/contrib/opencsd/decoder/source/ptm/trc_pkt_proc_ptm.cpp index 7c90b62e6413..668a14b73df0 100644 --- a/contrib/opencsd/decoder/source/ptm/trc_pkt_proc_ptm.cpp +++ b/contrib/opencsd/decoder/source/ptm/trc_pkt_proc_ptm.cpp @@ -224,6 +224,7 @@ void TrcPktProcPtm::InitProcessorState() m_waitASyncSOPkt = false; m_bAsyncRawOp = false; m_bOPNotSyncPkt = false; + m_excepAltISA = 0; m_curr_packet.ResetState(); InitPacketState(); @@ -559,7 +560,7 @@ void TrcPktProcPtm::pktWPointUpdate() m_gotExcepBytes = false; // mark as not got all required exception bytes thus far m_numExcepBytes = 0; // 0 read in - m_addrPktIsa = ocsd_isa_unknown; // not set by this packet as yet + m_addrPktIsa = ocsd_isa_unknown; // not set by this packet as yet } // collect all the bytes needed @@ -567,10 +568,12 @@ void TrcPktProcPtm::pktWPointUpdate() { if(readByte(currByte)) { + byteIdx = m_currPacketData.size() - 1; if(!m_gotAddrBytes) { - if(byteIdx < 4) + // byteIdx for address byte will run from 1 to 5 - first 4 my have continuation or not. + if(byteIdx <= 4) { // address bytes 1 - 4; // ISA stays the same diff --git a/contrib/opencsd/decoder/source/trc_core_arch_map.cpp b/contrib/opencsd/decoder/source/trc_core_arch_map.cpp index a26f79db996e..f25ab1e5ddfa 100644 --- a/contrib/opencsd/decoder/source/trc_core_arch_map.cpp +++ b/contrib/opencsd/decoder/source/trc_core_arch_map.cpp @@ -72,17 +72,6 @@ static ap_map_elem_t ap_map_array[] = { "Cortex-M4", { ARCH_V7, profile_CortexM } } }; -static ap_map_elem_t arch_map_array[] = -{ - { "ARMv7-A", { ARCH_V7, profile_CortexA } }, - { "ARMv7-R", { ARCH_V7, profile_CortexR } }, - { "ARMv7-M", { ARCH_V7, profile_CortexM } }, - { "ARMv8-A", { ARCH_V8, profile_CortexA } }, - { "ARMv8.3-A", { ARCH_V8r3, profile_CortexA } }, - { "ARMv8-R", { ARCH_V8, profile_CortexR } }, - { "ARMv8-M", { ARCH_V8, profile_CortexM } }, -}; - CoreArchProfileMap::CoreArchProfileMap() { unsigned i; @@ -90,10 +79,99 @@ CoreArchProfileMap::CoreArchProfileMap() { core_profiles[ap_map_array[i].name] = ap_map_array[i].ap; } - for (i = 0; i < sizeof(arch_map_array) / sizeof(_ap_map_elements); i++) - { - arch_profiles[arch_map_array[i].name] = arch_map_array[i].ap; - } } +ocsd_arch_profile_t CoreArchProfileMap::getArchProfile(const std::string &coreName) +{ + ocsd_arch_profile_t ap = { ARCH_UNKNOWN, profile_Unknown }; + bool bFound = false; + + std::map::const_iterator it; + + /* match against the core name map. */ + it = core_profiles.find(coreName); + if (it != core_profiles.end()) + { + ap = it->second; + bFound = true; + } + + /* try a pattern match on core name - pick up ARMvM[.m]-P and ARM-{aa|AA}64[-P] */ + if (!bFound) + ap = getPatternMatchCoreName(coreName); + + return ap; +} +ocsd_arch_profile_t CoreArchProfileMap::getPatternMatchCoreName(const std::string &coreName) +{ + ocsd_arch_profile_t ap = { ARCH_UNKNOWN, profile_Unknown }; + size_t pos; + + /* look for ARMvM[.m]-P */ + pos = coreName.find("ARMv"); + if (pos == 0) + { + int majver = coreName[4] - '0'; + int minver = 0; + int dotoffset = 0; + + pos = coreName.find_first_of("."); + if (pos == 5) { + minver = coreName[6] - '0'; + dotoffset = 2; + } + else if (pos != std::string::npos) + return ap; + + if (majver == 7) + ap.arch = ARCH_V7; + else if (majver >= 8) { + ap.arch = ARCH_AA64; /* default to 8.3+*/ + if (majver == 8) { + if (minver < 3) + ap.arch = ARCH_V8; + else if (minver == 3) + ap.arch = ARCH_V8r3; + } + } + else + return ap; /* no valid version - return unknown */ + + if (coreName.find_first_of("-", 4) == (size_t)(5 + dotoffset)) { + int profile_idx = 6 + dotoffset; + if (coreName[profile_idx] == 'A') + ap.profile = profile_CortexA; + else if (coreName[profile_idx] == 'R') + ap.profile = profile_CortexR; + else if (coreName[profile_idx] == 'M') + ap.profile = profile_CortexM; + else + ap.arch = ARCH_UNKNOWN; /*reset arch, return unknown*/ + } + else + ap.arch = ARCH_UNKNOWN; /*reset arch, return unknown*/ + return ap; + } + + /* look for ARM-{AA|aa}64[-P] */ + pos = coreName.find("ARM-"); + if (pos == 0) + { + pos = coreName.find("aa64"); + if (pos != 4) + pos = coreName.find("AA64"); + if (pos == 4) + { + ap.arch = ARCH_AA64; + ap.profile = profile_CortexA; + if (coreName.find_first_of("-", 7) == 8) { + if (coreName[9] == 'R') + ap.profile = profile_CortexR; + else if (coreName[9] == 'M') + ap.profile = profile_CortexM; + } + } + } + return ap; +} /* End of File trc_core_arch_map.cpp */ diff --git a/contrib/opencsd/decoder/source/trc_frame_deformatter.cpp b/contrib/opencsd/decoder/source/trc_frame_deformatter.cpp index 4d46854a655b..3b2aead875ca 100644 --- a/contrib/opencsd/decoder/source/trc_frame_deformatter.cpp +++ b/contrib/opencsd/decoder/source/trc_frame_deformatter.cpp @@ -54,7 +54,8 @@ TraceFmtDcdImpl::TraceFmtDcdImpl() : TraceComponent(DEFORMATTER_NAME), m_use_force_sync(false), m_alignment(16), // assume frame aligned data as default. m_b_output_packed_raw(false), - m_b_output_unpacked_raw(false) + m_b_output_unpacked_raw(false), + m_pStatsBlock(0) { resetStateParams(); @@ -244,7 +245,12 @@ ocsd_datapath_resp_t TraceFmtDcdImpl::processTraceData( if(m_trc_curr_idx != index) // none continuous trace data - throw an error. throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_DFMTR_NOTCONTTRACE,index); } - + + // record the incoming block for extraction routines to use. + m_in_block_base = pDataBlock; + m_in_block_size = dataBlockSize; + m_in_block_processed = 0; + if(dataBlockSize % m_alignment) // must be correctly aligned data { ocsdError err(OCSD_ERR_SEV_ERROR, OCSD_ERR_INVALID_PARAM_VAL); @@ -254,11 +260,6 @@ ocsd_datapath_resp_t TraceFmtDcdImpl::processTraceData( throw ocsdError(&err); } - // record the incoming block for extraction routines to use. - m_in_block_base = pDataBlock; - m_in_block_size = dataBlockSize; - m_in_block_processed = 0; - // processing loop... if(checkForSync()) { @@ -324,12 +325,18 @@ ocsd_err_t TraceFmtDcdImpl::DecodeConfigure(uint32_t flags) } else { + // alightment is the multiple of bytes the buffer size must be. m_cfgFlags = flags; + + // using memory aligned buffers, the formatter always outputs 16 byte frames so enforce + // this on the input m_alignment = 16; - if(flags & OCSD_DFRMTR_HAS_FSYNCS) - m_alignment = 4; - else if(flags & OCSD_DFRMTR_HAS_HSYNCS) + // if we have HSYNCS then always align to 2 byte buffers + if(flags & OCSD_DFRMTR_HAS_HSYNCS) m_alignment = 2; + // otherwise FSYNCS only can have 4 byte aligned buffers. + else if(flags & OCSD_DFRMTR_HAS_FSYNCS) + m_alignment = 4; } return err; } @@ -344,6 +351,7 @@ void TraceFmtDcdImpl::resetStateParams() // current frame processing m_ex_frm_n_bytes = 0; + m_b_fsync_start_eob = false; m_trc_curr_idx_sof = OCSD_BAD_TRC_INDEX; } @@ -415,20 +423,23 @@ void TraceFmtDcdImpl::outputUnsyncedBytes(uint32_t /*num_bytes*/) //**TBD: } -int TraceFmtDcdImpl::checkForResetFSyncPatterns() +ocsd_err_t TraceFmtDcdImpl::checkForResetFSyncPatterns(uint32_t &f_sync_bytes) { const uint32_t FSYNC_PATTERN = 0x7FFFFFFF; // LE host pattern for FSYNC bool check_for_fsync = true; int num_fsyncs = 0; - const uint8_t *dataPtr = m_in_block_base + m_in_block_processed; + uint32_t bytes_processed = m_in_block_processed; + const uint8_t *dataPtr = m_in_block_base + bytes_processed; + ocsd_err_t err = OCSD_OK; - while (check_for_fsync && (m_in_block_processed < m_in_block_size)) + while (check_for_fsync && (bytes_processed < m_in_block_size)) { // look for consecutive fsyncs as padding or for reset downstream - both cases will reset downstream.... if (*((uint32_t *)(dataPtr)) == FSYNC_PATTERN) { dataPtr += sizeof(uint32_t); - num_fsyncs++; + num_fsyncs++; + bytes_processed += sizeof(uint32_t); } else check_for_fsync = false; @@ -436,7 +447,6 @@ int TraceFmtDcdImpl::checkForResetFSyncPatterns() if (num_fsyncs) { - printf("Frame deformatter: Found %d FSYNCS\n",num_fsyncs); if ((num_fsyncs % 4) == 0) { // reset the upstream decoders @@ -449,32 +459,40 @@ int TraceFmtDcdImpl::checkForResetFSyncPatterns() } else { - // TBD: throw processing error, none frame size block of fsyncs + err = OCSD_ERR_DFMTR_BAD_FHSYNC; } } - return num_fsyncs * 4; + f_sync_bytes += num_fsyncs * 4; + return err; } - +/* Extract a single frame from the input buffer. */ bool TraceFmtDcdImpl::extractFrame() { const uint32_t FSYNC_PATTERN = 0x7FFFFFFF; // LE host pattern for FSYNC const uint16_t HSYNC_PATTERN = 0x7FFF; // LE host pattern for HSYNC + const uint16_t FSYNC_START = 0xFFFF; // LE host pattern for start 2 bytes of fsync - - bool cont_process = true; // continue processing after extraction. + ocsd_err_t err; uint32_t f_sync_bytes = 0; // skipped f sync bytes uint32_t h_sync_bytes = 0; // skipped h sync bytes uint32_t ex_bytes = 0; // extracted this pass (may be filling out part frame) + uint32_t buf_left = m_in_block_size - m_in_block_processed; // bytes remaining in buffer this pass. - // memory aligned sources are always multiples of frames, aligned to start. + // last call was end of input block - but carried on to process full frame. + // exit early here. + if (!buf_left) + return false; + + // memory aligned input data is forced to be always multiples of 16 byte frames, aligned to start. if( m_cfgFlags & OCSD_DFRMTR_FRAME_MEM_ALIGN) { // some linux drivers (e.g. for perf) will insert FSYNCS to pad or differentiate - // between blocks of aligned data, always in frame aligned complete 16 byte frames. + // between blocks of aligned data, always in frame aligned complete 16 byte frames. + // we need to skip past these frames, resetting as we go. if (m_cfgFlags & OCSD_DFRMTR_RESET_ON_4X_FSYNC) { - f_sync_bytes = checkForResetFSyncPatterns(); + err = checkForResetFSyncPatterns(f_sync_bytes); /* in this case the FSYNC pattern is output on both packed and unpacked cases */ if (f_sync_bytes && (m_b_output_packed_raw || m_b_output_unpacked_raw)) @@ -486,77 +504,96 @@ bool TraceFmtDcdImpl::extractFrame() m_in_block_base + m_in_block_processed, 0); } + + // throw processing error, none frame size block of fsyncs + if (err) + throw ocsdError(OCSD_ERR_SEV_ERROR, err, m_trc_curr_idx, "Incorrect FSYNC frame reset pattern"); + + buf_left -= f_sync_bytes; } - if((m_in_block_processed+f_sync_bytes) == m_in_block_size) + if (buf_left) { - m_ex_frm_n_bytes = 0; - cont_process = false; // end of input data. - } - else - { - // always a complete frame. - m_ex_frm_n_bytes = OCSD_DFRMTR_FRAME_SIZE; - memcpy(m_ex_frm_data, m_in_block_base + m_in_block_processed + f_sync_bytes, m_ex_frm_n_bytes); - m_trc_curr_idx_sof = m_trc_curr_idx + f_sync_bytes; - ex_bytes = OCSD_DFRMTR_FRAME_SIZE; + // always a complete frame - the input data has to be 16 byte multiple alignment. + m_ex_frm_n_bytes = OCSD_DFRMTR_FRAME_SIZE; + memcpy(m_ex_frm_data, m_in_block_base + m_in_block_processed + f_sync_bytes, m_ex_frm_n_bytes); + m_trc_curr_idx_sof = m_trc_curr_idx + f_sync_bytes; + ex_bytes = OCSD_DFRMTR_FRAME_SIZE; } } else { // extract data accounting for frame syncs and hsyncs if present. // we know we are aligned at this point - could be FSYNC or HSYNCs here. + // HSYNC present, library forces input to be aligned 2 byte multiples + // FSYNC - w/o HSYNCs, forces input to be aligned 4 byte multiples. // check what we a looking for - bool hasFSyncs = ((m_cfgFlags & OCSD_DFRMTR_HAS_FSYNCS) == OCSD_DFRMTR_HAS_FSYNCS); - bool hasHSyncs = ((m_cfgFlags & OCSD_DFRMTR_HAS_HSYNCS) == OCSD_DFRMTR_HAS_HSYNCS); + bool hasFSyncs = ((m_cfgFlags & OCSD_DFRMTR_HAS_FSYNCS) == OCSD_DFRMTR_HAS_FSYNCS); + bool hasHSyncs = ((m_cfgFlags & OCSD_DFRMTR_HAS_HSYNCS) == OCSD_DFRMTR_HAS_HSYNCS); + + const uint8_t* dataPtr = m_in_block_base + m_in_block_processed; + uint16_t data_pair_val; - const uint8_t *dataPtr = m_in_block_base+m_in_block_processed; - const uint8_t *eodPtr = m_in_block_base+m_in_block_size; - - cont_process = (bool)(dataPtr < eodPtr); - // can have FSYNCS at start of frame (in middle is an error). - if(hasFSyncs && cont_process && (m_ex_frm_n_bytes == 0)) + if (hasFSyncs && (m_ex_frm_n_bytes == 0)) { - while((*((uint32_t *)(dataPtr)) == FSYNC_PATTERN) && cont_process) + // was there an fsync start at the end of the last buffer? + if (m_b_fsync_start_eob) { + // last 2 of FSYNC look like HSYNC + if (*(uint16_t*)(dataPtr) != HSYNC_PATTERN) + { + // this means 0xFFFF followed by something else - invalid ID + ???? + throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_DFMTR_BAD_FHSYNC, m_trc_curr_idx, "Bad FSYNC pattern before frame or invalid ID.(0x7F)"); + } + else + { + f_sync_bytes += 2; + buf_left -= 2; + dataPtr += 2; + } + m_b_fsync_start_eob = false; + } + + // regular fsync checks + while ((buf_left >= 4) && (*((uint32_t*)(dataPtr)) == FSYNC_PATTERN)) { f_sync_bytes += 4; dataPtr += 4; - cont_process = (bool)(dataPtr < eodPtr); + buf_left -= 4; + } + + // handle possible part fsync at the end of a buffer + if (buf_left == 2) + { + if (*(uint16_t*)(dataPtr) == FSYNC_START) + { + f_sync_bytes += 2; + buf_left -= 2; + dataPtr += 2; + m_b_fsync_start_eob = true; + } } } - // not an FSYNC - while((m_ex_frm_n_bytes < OCSD_DFRMTR_FRAME_SIZE) && cont_process) + // process remaining data in pairs of bytes + while ((m_ex_frm_n_bytes < OCSD_DFRMTR_FRAME_SIZE) && buf_left) { - // check for illegal out of sequence FSYNC - if((m_ex_frm_n_bytes % 4) == 0) - { - if(*((uint32_t *)(dataPtr)) == FSYNC_PATTERN) - { - // throw an illegal FSYNC error - throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_DFMTR_BAD_FHSYNC, m_trc_curr_idx, "Bad FSYNC in frame."); - } - } - // mark start of frame after FSyncs - if(m_ex_frm_n_bytes == 0) + if (m_ex_frm_n_bytes == 0) m_trc_curr_idx_sof = m_trc_curr_idx + f_sync_bytes; m_ex_frm_data[m_ex_frm_n_bytes] = dataPtr[0]; - m_ex_frm_data[m_ex_frm_n_bytes+1] = dataPtr[1]; - m_ex_frm_n_bytes+=2; - ex_bytes +=2; + m_ex_frm_data[m_ex_frm_n_bytes + 1] = dataPtr[1]; + + data_pair_val = *((uint16_t*)(dataPtr)); // check pair is not HSYNC - if(*((uint16_t *)(dataPtr)) == HSYNC_PATTERN) + if (data_pair_val == HSYNC_PATTERN) { - if(hasHSyncs) + if (hasHSyncs) { - m_ex_frm_n_bytes-=2; - ex_bytes -= 2; - h_sync_bytes+=2; + h_sync_bytes += 2; } else { @@ -564,22 +601,27 @@ bool TraceFmtDcdImpl::extractFrame() throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_DFMTR_BAD_FHSYNC, m_trc_curr_idx, "Bad HSYNC in frame."); } } + // can't have a start of FSYNC here / illegal trace ID + else if (data_pair_val == FSYNC_START) + { + throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_DFMTR_BAD_FHSYNC, m_trc_curr_idx, "Bad FSYNC start in frame or invalid ID (0x7F)."); + } + else + { + m_ex_frm_n_bytes += 2; + ex_bytes += 2; + } + buf_left -= 2; dataPtr += 2; - cont_process = (bool)(dataPtr < eodPtr); } - - // if we hit the end of data but still have a complete frame waiting, - // need to continue processing to allow it to be used. - if(!cont_process && (m_ex_frm_n_bytes == OCSD_DFRMTR_FRAME_SIZE)) - cont_process = true; } // total bytes processed this pass uint32_t total_processed = ex_bytes + f_sync_bytes + h_sync_bytes; // output raw data on raw frame channel - packed raw. - if (((m_ex_frm_n_bytes == OCSD_DFRMTR_FRAME_SIZE) || !cont_process) && m_b_output_packed_raw) + if (((m_ex_frm_n_bytes == OCSD_DFRMTR_FRAME_SIZE) || (buf_left == 0)) && m_b_output_packed_raw) { outputRawMonBytes( OCSD_OP_DATA, m_trc_curr_idx, @@ -595,7 +637,11 @@ bool TraceFmtDcdImpl::extractFrame() // update index past the processed data m_trc_curr_idx += total_processed; - return cont_process; + // update any none trace data byte stats + addToFrameStats((uint64_t)(f_sync_bytes + h_sync_bytes)); + + // if we are exiting with a full frame then signal processing to continue + return (bool)(m_ex_frm_n_bytes == OCSD_DFRMTR_FRAME_SIZE); } bool TraceFmtDcdImpl::unpackFrame() @@ -604,6 +650,7 @@ bool TraceFmtDcdImpl::unpackFrame() uint8_t frameFlagBit = 0x1; uint8_t newSrcID = OCSD_BAD_CS_SRC_ID; bool PrevIDandIDChange = false; + uint64_t noneDataBytes = 0; // init output processing m_out_data_idx = 0; @@ -650,6 +697,7 @@ bool TraceFmtDcdImpl::unpackFrame() /// TBD - ID indexing in here. } + noneDataBytes++; } else // it's just data @@ -671,6 +719,7 @@ bool TraceFmtDcdImpl::unpackFrame() { // no matter if change or not, no associated data in byte 15 anyway so just set. m_curr_src_ID = (m_ex_frm_data[14] >> 1) & 0x7f; + noneDataBytes++; } // it's data else @@ -678,6 +727,9 @@ bool TraceFmtDcdImpl::unpackFrame() m_out_data[m_out_data_idx].data[m_out_data[m_out_data_idx].valid++] = m_ex_frm_data[14] | ((frameFlagBit & m_ex_frm_data[15]) ? 0x1 : 0x0); } m_ex_frm_n_bytes = 0; // mark frame as empty; + + noneDataBytes++; // byte 15 is always non-data. + addToFrameStats(noneDataBytes); // update the non data byte stats. return true; } @@ -716,6 +768,8 @@ bool TraceFmtDcdImpl::outputFrame() m_out_data[m_out_processed].data + m_out_data[m_out_processed].used, &bytes_used)); + addToIDStats((uint64_t)bytes_used); + if(!dataPathCont()) { cont_processing = false; @@ -739,7 +793,12 @@ bool TraceFmtDcdImpl::outputFrame() m_out_data[m_out_processed].valid, m_out_data[m_out_processed].data, m_out_data[m_out_processed].id); - } + } + + if (isReservedID(m_out_data[m_out_processed].id)) + addToReservedIDStats((uint64_t)m_out_data[m_out_processed].valid); + else + addToNoIDStats((uint64_t)m_out_data[m_out_processed].valid); m_out_processed++; // skip past this data. } } @@ -754,13 +813,44 @@ bool TraceFmtDcdImpl::outputFrame() m_out_data[m_out_processed].valid, m_out_data[m_out_processed].data, m_out_data[m_out_processed].id); - } + } + addToUnknownIDStats((uint64_t)m_out_data[m_out_processed].valid); m_out_processed++; // skip past this data. } } return cont_processing; } + +void TraceFmtDcdImpl::addToIDStats(uint64_t val) +{ + if (m_pStatsBlock) + m_pStatsBlock->valid_id_bytes += val; +} +void TraceFmtDcdImpl::addToNoIDStats(uint64_t val) +{ + if (m_pStatsBlock) + m_pStatsBlock->no_id_bytes += val; +} + +void TraceFmtDcdImpl::addToFrameStats(uint64_t val) +{ + if (m_pStatsBlock) + m_pStatsBlock->frame_bytes += val; +} + +void TraceFmtDcdImpl::addToUnknownIDStats(uint64_t val) +{ + if (m_pStatsBlock) + m_pStatsBlock->unknown_id_bytes += val; +} + +void TraceFmtDcdImpl::addToReservedIDStats(uint64_t val) +{ + if (m_pStatsBlock) + m_pStatsBlock->reserved_id_bytes += val; +} + /***************************************************************/ /* interface */ /***************************************************************/ @@ -819,21 +909,27 @@ componentAttachPt *TraceFormatterFrameDecoder::getErrLogAttachPt return (m_pDecoder != 0) ? m_pDecoder->getErrorLogAttachPt() : 0; } -/* configuration - set operational mode for incoming stream (has FSYNCS etc) */ -ocsd_err_t TraceFormatterFrameDecoder::Configure(uint32_t cfg_flags) +ocsd_err_t TraceFormatterFrameDecoder::Init() { - if(!m_pDecoder) - { - if(m_instNum >= 0) + if (!m_pDecoder) + { + if (m_instNum >= 0) m_pDecoder = new (std::nothrow) TraceFmtDcdImpl(m_instNum); else m_pDecoder = new (std::nothrow) TraceFmtDcdImpl(); - if(!m_pDecoder) return OCSD_ERR_MEM; + if (!m_pDecoder) return OCSD_ERR_MEM; } - m_pDecoder->DecodeConfigure(cfg_flags); return OCSD_OK; } +/* configuration - set operational mode for incoming stream (has FSYNCS etc) */ +ocsd_err_t TraceFormatterFrameDecoder::Configure(uint32_t cfg_flags) +{ + if (!m_pDecoder) + return OCSD_ERR_NOT_INIT; + return m_pDecoder->DecodeConfigure(cfg_flags); +} + const uint32_t TraceFormatterFrameDecoder::getConfigFlags() const { uint32_t flags = 0; @@ -865,5 +961,10 @@ ocsd_datapath_resp_t TraceFormatterFrameDecoder::Flush() return (m_pDecoder == 0) ? OCSD_RESP_FATAL_NOT_INIT : m_pDecoder->Flush(); } +void TraceFormatterFrameDecoder::SetDemuxStatsBlock(ocsd_demux_stats_t *pStatsBlock) +{ + if (m_pDecoder) + m_pDecoder->SetDemuxStatsBlock(pStatsBlock); +} /* End of File trc_frame_deformatter.cpp */ diff --git a/contrib/opencsd/decoder/source/trc_frame_deformatter_impl.h b/contrib/opencsd/decoder/source/trc_frame_deformatter_impl.h index e1fc17ab259f..3571d5f2fc47 100644 --- a/contrib/opencsd/decoder/source/trc_frame_deformatter_impl.h +++ b/contrib/opencsd/decoder/source/trc_frame_deformatter_impl.h @@ -75,6 +75,8 @@ class TraceFmtDcdImpl : public TraceComponent, ITrcDataIn ocsd_err_t DecodeConfigure(uint32_t flags); ocsd_err_t SetForcedSyncIndex(ocsd_trc_index_t index, bool bSet); + void SetDemuxStatsBlock(ocsd_demux_stats_t *pStatsBlock) { m_pStatsBlock = pStatsBlock; }; + private: ocsd_datapath_resp_t executeNoneDataOpAllIDs(ocsd_datapath_op_t op, const ocsd_trc_index_t index = 0); ocsd_datapath_resp_t processTraceData(const ocsd_trc_index_t index, @@ -113,12 +115,20 @@ class TraceFmtDcdImpl : public TraceComponent, ITrcDataIn void setRawChanFilterAll(bool bEnable); const bool rawChanEnabled(const uint8_t id) const; - int checkForResetFSyncPatterns(); + ocsd_err_t checkForResetFSyncPatterns(uint32_t &f_sync_bytes); friend class TraceFormatterFrameDecoder; - // attachment points + // stats updates + void addToIDStats(uint64_t val); + void addToNoIDStats(uint64_t val); + void addToFrameStats(uint64_t val); + void addToUnknownIDStats(uint64_t val); + void addToReservedIDStats(uint64_t val); + + bool isReservedID(uint8_t ID) { return ((ID == 0) || (ID >= 0x70)); }; + // attachment points componentAttachPt m_IDStreams[128]; componentAttachPt m_RawTraceFrame; @@ -142,12 +152,18 @@ class TraceFmtDcdImpl : public TraceComponent, ITrcDataIn // incoming frame buffer uint8_t m_ex_frm_data[OCSD_DFRMTR_FRAME_SIZE]; // buffer the current frame in case we have to stop part way through int m_ex_frm_n_bytes; // number of valid bytes in the current frame (extraction) + bool m_b_fsync_start_eob; // flag to indicate that the end of the last buffer was a pair of bytes + // (0xffff) that could only validly be the start and FSYNC. ocsd_trc_index_t m_trc_curr_idx_sof; // trace source index at start of frame. - // channel output data - can never be more than a frame of data for a single ID. - out_chan_data m_out_data[7]; // can only be 8 ID changes in a frame, but last on has no associated data so 7 possible data blocks + /* channel output data - can never be more than a frame of data for a single ID. + * 8 possible ID changes per frame. Although the final one can have no associated data, a pathological + * case exists with 7 ID changes, all data associated with a previous frame, except for last + * ID / data byte which is data. Not possible with normal hardware but guard against corrupt input. + */ + out_chan_data m_out_data[8]; // output data for a given ID int m_out_data_idx; // number of out_chan_data frames used. - int m_out_processed; // number of complete out_chan_data frames output. + int m_out_processed; // number of complete out_chan_data frames output. /* local copy of input buffer pointers*/ const uint8_t *m_in_block_base; @@ -159,6 +175,8 @@ class TraceFmtDcdImpl : public TraceComponent, ITrcDataIn bool m_b_output_unpacked_raw; bool m_raw_chan_enable[128]; + + ocsd_demux_stats_t *m_pStatsBlock; }; diff --git a/contrib/opencsd/decoder/source/trc_gen_elem.cpp b/contrib/opencsd/decoder/source/trc_gen_elem.cpp index e1774203ebc5..c94c5a7c6848 100644 --- a/contrib/opencsd/decoder/source/trc_gen_elem.cpp +++ b/contrib/opencsd/decoder/source/trc_gen_elem.cpp @@ -54,7 +54,10 @@ static const char *s_elem_descs[][2] = {"OCSD_GEN_TRC_ELEM_TIMESTAMP","Timestamp - preceding elements happeded before this time."}, {"OCSD_GEN_TRC_ELEM_CYCLE_COUNT","Cycle count - cycles since last cycle count value - associated with a preceding instruction range."}, {"OCSD_GEN_TRC_ELEM_EVENT","Event - numbered event or trigger"}, - {"OCSD_GEN_TRC_ELEM_SWTRACE","Software trace packet - may contain data payload."}, + {"OCSD_GEN_TRC_ELEM_SWTRACE","Software trace packet - may contain data payload. STM / ITM hardware trace with channel protocol."}, + {"OCSD_GEN_TRC_ELEM_SYNC_MARKER","Synchronisation marker - marks position in stream of an element that is output later."}, + {"OCSD_GEN_TRC_ELEM_MEMTRANS","Trace indication of transactional memory operations."}, + {"OCSD_GEN_TRC_ELEM_INSTRUMENTATION", "PE instrumentation trace - PE generated SW trace, application dependent protocol."}, {"OCSD_GEN_TRC_ELEM_CUSTOM","Fully custom packet type."} }; @@ -64,7 +67,8 @@ static const char *instr_type[] = { "iBR ", "ISB ", "DSB.DMB", - "WFI.WFE" + "WFI.WFE", + "TSTART" }; #define T_SIZE (sizeof(instr_type) / sizeof(const char *)) @@ -105,6 +109,16 @@ static const char *s_unsync_reason[] = { "bad-packet", // UNSYNC_BAD_PACKET - bad packet at input - resync to restart. "end-of-trace", // UNSYNC_EOT - end of trace info. }; +static const char *s_transaction_type[] = { + "Init", + "Start", + "Commit", + "Fail" +}; + +static const char *s_marker_t[] = { + "Timestamp marker", // ELEM_MARKER_TS +}; void OcsdTraceElement::toString(std::string &str) const { @@ -158,7 +172,14 @@ void OcsdTraceElement::toString(std::string &str) const { oss << "EL" << std::dec << (int)(context.exception_level); } - oss << (context.security_level == ocsd_sec_secure ? "S; " : "N; ") << (context.bits64 ? "64-bit; " : "32-bit; "); + switch (context.security_level) + { + case ocsd_sec_secure: oss << "S; "; break; + case ocsd_sec_nonsecure: oss << "N; "; break; + case ocsd_sec_root: oss << "Root; "; break; + case ocsd_sec_realm: oss << "Realm; "; break; + } + oss << (context.bits64 ? "64-bit; " : "32-bit; "); if(context.vmid_valid) oss << "VMID=0x" << std::hex << context.vmid << "; "; if(context.ctxt_id_valid) @@ -190,6 +211,19 @@ void OcsdTraceElement::toString(std::string &str) const oss << " [" << s_unsync_reason[unsync_eot_info] << "]"; break; + case OCSD_GEN_TRC_ELEM_SYNC_MARKER: + oss << " [" << s_marker_t[sync_marker.type] << "(0x" << std::setfill('0') << std::setw(8) << std::hex << sync_marker.value << ")]"; + break; + + case OCSD_GEN_TRC_ELEM_MEMTRANS: + if (mem_trans <= OCSD_MEM_TRANS_FAIL) + oss << s_transaction_type[mem_trans]; + break; + + case OCSD_GEN_TRC_ELEM_INSTRUMENTATION: + oss << "EL" << std::dec << (int)sw_ite.el << "; 0x" << std::setfill('0') << std::setw(16) << std::hex << sw_ite.value; + break; + default: break; } if(has_cc) diff --git a/contrib/opencsd/decoder/source/trc_printable_elem.cpp b/contrib/opencsd/decoder/source/trc_printable_elem.cpp index 88c7bb226f41..2b60c030d53f 100644 --- a/contrib/opencsd/decoder/source/trc_printable_elem.cpp +++ b/contrib/opencsd/decoder/source/trc_printable_elem.cpp @@ -52,8 +52,6 @@ void trcPrintableElem::getValStr(std::string &valStr, const int valTotalBitSize, assert((valTotalBitSize >= 4) && (valTotalBitSize <= 64)); - uint64_t LimitMask = ~0ULL; - LimitMask >>= 64-valTotalBitSize; valStr = "0x"; if(asHex)