diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index f0de93deb858..29d85efcb00a 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -36,6 +36,9 @@ # xargs -n1 | sort | uniq -d; # done +# 20200617: update opencsd to 0.14.2 +OLD_FILES+=usr/include/opencsd/etmv4/trc_pkt_elem_etmv4d.h + # 20200606: retire binutils build infrastructure .if !defined(WITH_PORT_BASE_BINUTILS) OLD_FILES+=usr/bin/as diff --git a/contrib/opencsd/decoder/include/common/ocsd_dcd_mngr.h b/contrib/opencsd/decoder/include/common/ocsd_dcd_mngr.h index ba7d8a89c46f..3342eacb24ca 100644 --- a/contrib/opencsd/decoder/include/common/ocsd_dcd_mngr.h +++ b/contrib/opencsd/decoder/include/common/ocsd_dcd_mngr.h @@ -115,6 +115,9 @@ ocsd_err_t DecoderMngrBase::createDecoder(const int create_flags, cons if(!pkt_proc) return OCSD_ERR_MEM; + // set the op mode flags + pkt_proc->setComponentOpMode(create_flags & (OCSD_OPFLG_COMP_MODE_MASK | OCSD_OPFLG_PKTPROC_COMMON)); + // set the configuration TrcPktProcBase *pProcBase = dynamic_cast< TrcPktProcBase *>(pkt_proc); if(pProcBase == 0) @@ -133,6 +136,9 @@ ocsd_err_t DecoderMngrBase::createDecoder(const int create_flags, cons if(!pkt_dcd) return OCSD_ERR_MEM; + // set the op mode flags + pkt_dcd->setComponentOpMode(create_flags & (OCSD_OPFLG_COMP_MODE_MASK | OCSD_OPFLG_PKTDEC_COMMON)); + // get the decoder base TrcPktDecodeBase *pBase = dynamic_cast< TrcPktDecodeBase *>(pkt_dcd); if(pBase == 0) diff --git a/contrib/opencsd/decoder/include/common/ocsd_gen_elem_list.h b/contrib/opencsd/decoder/include/common/ocsd_gen_elem_list.h index 0ff1bd59cbbe..2dab240140bf 100644 --- a/contrib/opencsd/decoder/include/common/ocsd_gen_elem_list.h +++ b/contrib/opencsd/decoder/include/common/ocsd_gen_elem_list.h @@ -1,6 +1,6 @@ /* - * \file ocsd_gen_elem_stack.h - * \brief OpenCSD : Generic element output stack. + * \file ocsd_gen_elem_list.h + * \brief OpenCSD : Generic element output list. * * \copyright Copyright (c) 2016, ARM Limited. All Rights Reserved. */ @@ -47,7 +47,7 @@ * This should remove some of the requirement on the packet processing to be re-enterant, * simplifying this code. * - * Last element(s) on this stack can be marked pending to allow for later cancellation. + * Last element(s) on this list can be marked pending to allow for later cancellation. * (This required for cancel element in ETMv3 exeception branch). * * The "list" is actually a ring buffer - maintaining pointers to indicate current valid elements. @@ -150,4 +150,4 @@ inline void OcsdGenElemList::initSendIf(componentAttachPt *pGenEl m_sendIf = pGenElemIf; } -/* End of File ocsd_gen_elem_stack.h */ +/* End of File ocsd_gen_elem_list.h */ diff --git a/contrib/opencsd/decoder/include/common/ocsd_gen_elem_stack.h b/contrib/opencsd/decoder/include/common/ocsd_gen_elem_stack.h new file mode 100644 index 000000000000..64c525df4270 --- /dev/null +++ b/contrib/opencsd/decoder/include/common/ocsd_gen_elem_stack.h @@ -0,0 +1,109 @@ +/* +* \file ocsd_gen_elem_stack.h +* \brief OpenCSD : Generic element output stack. +* +* \copyright Copyright (c) 2020, 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 "trc_gen_elem.h" +#include "comp_attach_pt_t.h" +#include "interfaces/trc_gen_elem_in_i.h" + +/* element stack to handle cases where a trace element can generate multiple output packets + + maintains the "current" element, which might be sent independently of this stack, and also + ensures that persistent data in the output elements is maintained between elements. +*/ +class OcsdGenElemStack +{ +public: + OcsdGenElemStack(); + ~OcsdGenElemStack(); + + void initSendIf(componentAttachPt *pGenElemIf); + void initCSID(const uint8_t CSID) { m_CSID = CSID; }; + + OcsdTraceElement &getCurrElem(); //!< get the current element. + ocsd_err_t resetElemStack(); //!< set pointers to base of stack + ocsd_err_t addElem(const ocsd_trc_index_t trc_pkt_idx); //!< add elem to stack and set current. + void setCurrElemIdx(const ocsd_trc_index_t trc_pkt_idx); //!< packet index for this element + ocsd_err_t addElemType(const ocsd_trc_index_t trc_pkt_idx, ocsd_gen_trc_elem_t elem_type); + + ocsd_datapath_resp_t sendElements(); //!< send elements on the stack + const int numElemToSend() const; + +private: + typedef struct _elemPtr { + OcsdTraceElement *pElem; //!< pointer to the listed trace element + ocsd_trc_index_t trc_pkt_idx; //!< packet index in the trace stream + } elemPtr_t; + + const bool isInit(); //!< check correctly initialised. + + ocsd_err_t growArray(); + void copyPersistentData(int src, int dst); //!< copy across persistent state data between elements + void resetIndexes(); //!< clear down all indexes - reset or send complete. + + elemPtr_t *m_pElemArray; //!< an array of pointers to elements. + int m_elemArraySize; //!< number of element pointers in the array + + int m_elem_to_send; //!< number of live elements in the stack - init to 1. + int m_curr_elem_idx; //!< index into the element array. + int m_send_elem_idx; //!< next element to send. + + //!< send packet info + uint8_t m_CSID; + componentAttachPt *m_sendIf; //!< element send interface. + + bool m_is_init; +}; + +inline const int OcsdGenElemStack::numElemToSend() const +{ + return m_elem_to_send; +} + +inline void OcsdGenElemStack::initSendIf(componentAttachPt *pGenElemIf) +{ + m_sendIf = pGenElemIf; +} + +inline void OcsdGenElemStack::setCurrElemIdx(const ocsd_trc_index_t trc_pkt_idx) +{ + m_pElemArray[m_curr_elem_idx].trc_pkt_idx = trc_pkt_idx; +} + +inline OcsdTraceElement &OcsdGenElemStack::getCurrElem() +{ + return *(m_pElemArray[m_curr_elem_idx].pElem); +} + + +/* End of File ocsd_gen_elem_stack.h */ 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 5a24149180fc..b72b4b411fa4 100644 --- a/contrib/opencsd/decoder/include/common/trc_core_arch_map.h +++ b/contrib/opencsd/decoder/include/common/trc_core_arch_map.h @@ -39,6 +39,23 @@ #include #include "opencsd/ocsd_if_types.h" +/** @class CoreArchProfileMap + * + * @brief Map core / arch name to profile for decoder. + * + * Helper class for library clients to map core or architecture version names onto + * a profile / arch version pair suitable for use with the decode library. + * + * Valid core names are:- + * - Cortex-Axx : where xx = 5,7,12,15,17,32,35,53,55,57,65,72,73,75,76,77; + * - Cortex-Rxx : where xx = 5,7,8,52; + * - Cortex-Mxx : where xx = 0,0+,3,4,23,33; + * + * Valid architecture profile names are:- + * - ARMv7-A, ARMv7-R, ARMv7-M; + * - ARMv8-A, ARMv8.3A, ARMv8-R, ARMv8-M; + * + */ class CoreArchProfileMap { public: @@ -50,16 +67,31 @@ class CoreArchProfileMap private: 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()) + 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; } diff --git a/contrib/opencsd/decoder/include/common/trc_gen_elem.h b/contrib/opencsd/decoder/include/common/trc_gen_elem.h index 1c4a47b3aa0a..5d8983a8c274 100644 --- a/contrib/opencsd/decoder/include/common/trc_gen_elem.h +++ b/contrib/opencsd/decoder/include/common/trc_gen_elem.h @@ -72,6 +72,7 @@ class OcsdTraceElement : public trcPrintableElem, public ocsd_generic_trace_elem void setTraceOnReason(const trace_on_reason_t reason); + void setUnSyncEOTReason(const unsync_info_t reason); 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); @@ -94,7 +95,8 @@ class OcsdTraceElement : public trcPrintableElem, public ocsd_generic_trace_elem // return current context const ocsd_pe_context &getContext() const { return context; }; - + void copyPersistentData(const OcsdTraceElement &src); + private: void printSWInfoPkt(std::ostringstream &oss) const; void clearPerPktData(); //!< clear flags that indicate validity / have values on a per packet basis @@ -171,8 +173,8 @@ inline void OcsdTraceElement::init() inline void OcsdTraceElement::clearPerPktData() { - flag_bits = 0; // union with trace_on_reason / trace_event - + flag_bits = 0; // bit-field with various flags. + exception_number = 0; // union with trace_on_reason / trace_event ptr_extended_data = 0; // extended data pointer } @@ -181,6 +183,11 @@ inline void OcsdTraceElement::setTraceOnReason(const trace_on_reason_t reason) trace_on_reason = reason; } +inline void OcsdTraceElement::setUnSyncEOTReason(const unsync_info_t reason) +{ + unsync_eot_info = reason; +} + inline void OcsdTraceElement::setISA(const ocsd_isa isa_update) { isa = isa_update; @@ -201,6 +208,12 @@ inline void OcsdTraceElement::setExtendedDataPtr(const void *data_ptr) ptr_extended_data = data_ptr; } +// set persistent data between output packets. +inline void OcsdTraceElement::copyPersistentData(const OcsdTraceElement &src) +{ + isa = src.isa; + context = src.context; +} /** @}*/ 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 2bbf5e51d878..da702068f372 100644 --- a/contrib/opencsd/decoder/include/common/trc_pkt_decode_base.h +++ b/contrib/opencsd/decoder/include/common/trc_pkt_decode_base.h @@ -85,7 +85,10 @@ class TrcPktDecodeI : public TraceComponent virtual ocsd_err_t onProtocolConfig() = 0; virtual const uint8_t getCoreSightTraceID() = 0; + /* init handling */ const bool checkInit(); + /* Called on first init confirmation */ + virtual void onFirstInitOK() {}; /* data output */ ocsd_datapath_resp_t outputTraceElement(const OcsdTraceElement &elem); // use current index @@ -147,6 +150,8 @@ inline const bool TrcPktDecodeI::checkInit() init_err_msg = "No instruction decoder interface attached and enabled"; else m_decode_init_ok = true; + if (m_decode_init_ok) + onFirstInitOK(); } return m_decode_init_ok; } diff --git a/contrib/opencsd/decoder/include/common/trc_raw_buffer.h b/contrib/opencsd/decoder/include/common/trc_raw_buffer.h new file mode 100644 index 000000000000..67b8d2403457 --- /dev/null +++ b/contrib/opencsd/decoder/include/common/trc_raw_buffer.h @@ -0,0 +1,96 @@ +/* +* \file trc_raw_buffer.h +* \brief OpenCSD : Trace raw data byte buffer +* +* \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_RAW_BUFFER_H_INCLUDED +#define ARM_TRC_RAW_BUFFER_H_INCLUDED + +#include + +class TraceRawBuffer +{ +public: + TraceRawBuffer() : + m_bufSize(0), + m_bufProcessed(0), + m_pBuffer(0), + pkt(0) + {}; + ~TraceRawBuffer() {}; + + // init the buffer + void init(const uint32_t size, const uint8_t *rawtrace, std::vector *out_packet); + void copyByteToPkt(); // move a byte to the packet buffer + uint8_t peekNextByte(); // value of next byte in buffer. + + bool empty() { return m_bufProcessed == m_bufSize; }; + // bytes processed. + uint32_t processed() { return m_bufProcessed; }; + // buffer size; + uint32_t size() { return m_bufSize; } + +private: + uint32_t m_bufSize; + uint32_t m_bufProcessed; + const uint8_t *m_pBuffer; + std::vector *pkt; + +}; + +// init the buffer +inline void TraceRawBuffer::init(const uint32_t size, const uint8_t *rawtrace, std::vector *out_packet) +{ + m_bufSize = size; + m_bufProcessed = 0; + m_pBuffer = rawtrace; + pkt = out_packet; +} + +inline void TraceRawBuffer::copyByteToPkt() +{ + if (!empty()) { + pkt->push_back(m_pBuffer[m_bufProcessed]); + m_bufProcessed++; + } +} + +inline uint8_t TraceRawBuffer::peekNextByte() +{ + uint8_t val = 0; + if (!empty()) + val = m_pBuffer[m_bufProcessed]; + return val; +} + +#endif // ARM_TRC_RAW_BUFFER_H_INCLUDED + diff --git a/contrib/opencsd/decoder/include/i_dec/trc_i_decode.h b/contrib/opencsd/decoder/include/i_dec/trc_i_decode.h index 0285f4182523..d519a3aca7be 100644 --- a/contrib/opencsd/decoder/include/i_dec/trc_i_decode.h +++ b/contrib/opencsd/decoder/include/i_dec/trc_i_decode.h @@ -46,10 +46,9 @@ class TrcIDecode : public IInstrDecode virtual ocsd_err_t DecodeInstruction(ocsd_instr_info *instr_info); private: - ocsd_err_t DecodeA32(ocsd_instr_info *instr_info); - ocsd_err_t DecodeA64(ocsd_instr_info *instr_info); - ocsd_err_t DecodeT32(ocsd_instr_info *instr_info); - void SetArchVersion(ocsd_instr_info *instr_info); + ocsd_err_t DecodeA32(ocsd_instr_info *instr_info, struct decode_info *info); + ocsd_err_t DecodeA64(ocsd_instr_info *instr_info, struct decode_info *info); + ocsd_err_t DecodeT32(ocsd_instr_info *instr_info, struct decode_info *info); }; #endif // ARM_TRC_I_DECODE_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 8697f68d676c..911b0cf7db95 100644 --- a/contrib/opencsd/decoder/include/i_dec/trc_idec_arminst.h +++ b/contrib/opencsd/decoder/include/i_dec/trc_idec_arminst.h @@ -42,6 +42,12 @@ #include "opencsd/ocsd_if_types.h" #include +/* supplementary decode information */ +struct decode_info { + uint16_t arch_version; + ocsd_instr_subtype instr_sub_type; +}; + /* For Thumb2, test if a halfword is the first half of a 32-bit instruction, as opposed to a complete 16-bit instruction. @@ -63,19 +69,19 @@ instructions that write to the PC. It does not include exception instructions such as SVC, HVC and SMC. (Performance event 0x0C includes these.) */ -int inst_ARM_is_branch(uint32_t inst); -int inst_Thumb_is_branch(uint32_t inst); -int inst_A64_is_branch(uint32_t inst); +int inst_ARM_is_branch(uint32_t inst, struct decode_info *info); +int inst_Thumb_is_branch(uint32_t inst, struct decode_info *info); +int inst_A64_is_branch(uint32_t inst, struct decode_info *info); /* Test whether an instruction is a direct (aka immediate) branch. Performance event 0x0D counts these. */ int inst_ARM_is_direct_branch(uint32_t inst); -int inst_Thumb_is_direct_branch(uint32_t inst); -int inst_Thumb_is_direct_branch_link(uint32_t inst, uint8_t *is_link, uint8_t *is_cond); -int inst_A64_is_direct_branch(uint32_t inst); -int inst_A64_is_direct_branch_link(uint32_t inst, uint8_t *is_link); +int inst_Thumb_is_direct_branch(uint32_t inst, struct decode_info *info); +int inst_Thumb_is_direct_branch_link(uint32_t inst, uint8_t *is_link, uint8_t *is_cond, struct decode_info *info); +int inst_A64_is_direct_branch(uint32_t inst, struct decode_info *info); +int inst_A64_is_direct_branch_link(uint32_t inst, uint8_t *is_link, struct decode_info *info); /* Get branch destination for a direct branch. @@ -84,15 +90,15 @@ int inst_ARM_branch_destination(uint32_t addr, uint32_t inst, uint32_t *pnpc); int inst_Thumb_branch_destination(uint32_t addr, uint32_t inst, uint32_t *pnpc); int inst_A64_branch_destination(uint64_t addr, uint32_t inst, uint64_t *pnpc); -int inst_ARM_is_indirect_branch(uint32_t inst); -int inst_Thumb_is_indirect_branch_link(uint32_t inst, uint8_t *is_link); -int inst_Thumb_is_indirect_branch(uint32_t inst); -int inst_A64_is_indirect_branch_link(uint32_t inst, uint8_t *is_link); -int inst_A64_is_indirect_branch(uint32_t inst); +int inst_ARM_is_indirect_branch(uint32_t inst, struct decode_info *info); +int inst_Thumb_is_indirect_branch_link(uint32_t inst, uint8_t *is_link, struct decode_info *info); +int inst_Thumb_is_indirect_branch(uint32_t inst, struct decode_info *info); +int inst_A64_is_indirect_branch_link(uint32_t inst, uint8_t *is_link, struct decode_info *info); +int inst_A64_is_indirect_branch(uint32_t inst, struct decode_info *info); -int inst_ARM_is_branch_and_link(uint32_t inst); -int inst_Thumb_is_branch_and_link(uint32_t inst); -int inst_A64_is_branch_and_link(uint32_t inst); +int inst_ARM_is_branch_and_link(uint32_t inst, struct decode_info *info); +int inst_Thumb_is_branch_and_link(uint32_t inst, struct decode_info *info); +int inst_A64_is_branch_and_link(uint32_t inst, struct decode_info *info); int inst_ARM_is_conditional(uint32_t inst); int inst_Thumb_is_conditional(uint32_t inst); @@ -128,14 +134,6 @@ int inst_ARM_is_UDF(uint32_t inst); int inst_Thumb_is_UDF(uint32_t inst); int inst_A64_is_UDF(uint32_t inst); - -/* access sub-type information */ -ocsd_instr_subtype get_instr_subtype(); -void clear_instr_subtype(); - -/* set arch version info. */ -void set_arch_version(uint16_t version); - #endif // ARM_TRC_IDEC_ARMINST_H_INCLUDED /* End of File trc_idec_arminst.h */ diff --git a/contrib/opencsd/decoder/include/mem_acc/trc_mem_acc_bufptr.h b/contrib/opencsd/decoder/include/mem_acc/trc_mem_acc_bufptr.h index bd9ea8ee1e5d..b6208a7d8a13 100644 --- a/contrib/opencsd/decoder/include/mem_acc/trc_mem_acc_bufptr.h +++ b/contrib/opencsd/decoder/include/mem_acc/trc_mem_acc_bufptr.h @@ -68,7 +68,6 @@ class TrcMemAccBufPtr: public TrcMemAccessorBase private: const uint8_t *m_p_buffer; /**< pointer to the memory buffer */ - const uint32_t m_size; /**< size of the memory buffer. */ }; #endif // ARM_TRC_MEM_ACC_BUFPTR_H_INCLUDED diff --git a/contrib/opencsd/decoder/include/opencsd/etmv3/trc_pkt_decode_etmv3.h b/contrib/opencsd/decoder/include/opencsd/etmv3/trc_pkt_decode_etmv3.h index b2139c0d9e68..902770655a53 100644 --- a/contrib/opencsd/decoder/include/opencsd/etmv3/trc_pkt_decode_etmv3.h +++ b/contrib/opencsd/decoder/include/opencsd/etmv3/trc_pkt_decode_etmv3.h @@ -264,6 +264,7 @@ class TrcPktDecodeEtmV3 : public TrcPktDecodeBase } processor_state_t; processor_state_t m_curr_state; + unsync_info_t m_unsync_info; //!< additional state for unsync uint8_t m_CSID; //!< Coresight trace ID for this decoder. }; diff --git a/contrib/opencsd/decoder/include/opencsd/etmv4/etmv4_decoder.h b/contrib/opencsd/decoder/include/opencsd/etmv4/etmv4_decoder.h index 05bdd44d683e..5d183631a721 100644 --- a/contrib/opencsd/decoder/include/opencsd/etmv4/etmv4_decoder.h +++ b/contrib/opencsd/decoder/include/opencsd/etmv4/etmv4_decoder.h @@ -38,7 +38,6 @@ #include "trc_cmp_cfg_etmv4.h" #include "trc_pkt_elem_etmv4i.h" -#include "trc_pkt_elem_etmv4d.h" #include "trc_pkt_proc_etmv4.h" #include "trc_pkt_types_etmv4.h" #include "trc_pkt_decode_etmv4i.h" 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 15996547163c..5a283c541f3e 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 @@ -56,6 +56,7 @@ typedef enum _p0_elem_t P0_TS, P0_CC, P0_TS_CC, + P0_Q, P0_OVERFLOW, P0_FUNC_RET, } p0_elem_t; @@ -119,6 +120,44 @@ inline TrcStackElemAddr::TrcStackElemAddr(const ocsd_etmv4_i_pkt_type root_pkt, m_addr_val.isa = 0; } +/************************************************************/ +/** Q element */ +class TrcStackQElem : public TrcStackElem +{ +protected: + TrcStackQElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index); + virtual ~TrcStackQElem() {}; + + friend class EtmV4P0Stack; + +public: + void setInstrCount(const int instr_count) { m_instr_count = instr_count; }; + const int getInstrCount() const { return m_instr_count; } + + void setAddr(const etmv4_addr_val_t &addr_val) + { + m_addr_val = addr_val; + m_has_addr = true; + }; + const etmv4_addr_val_t &getAddr() const { return m_addr_val; }; + const bool hasAddr() const { return m_has_addr; }; + +private: + bool m_has_addr; + etmv4_addr_val_t m_addr_val; + int m_instr_count; + +}; + +inline TrcStackQElem::TrcStackQElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) : + TrcStackElem(P0_Q , true, root_pkt, root_index) +{ + m_addr_val.val = 0; + m_addr_val.isa = 0; + m_has_addr = false; + m_instr_count = 0; +} + /************************************************************/ /** Context element */ @@ -133,9 +172,12 @@ class TrcStackElemCtxt : public TrcStackElem public: void setContext(const etmv4_context_t &ctxt) { m_context = ctxt; }; const etmv4_context_t &getContext() const { return m_context; }; + void setIS(const uint8_t IS) { m_IS = IS; }; + const uint8_t getIS() const { return m_IS; }; private: etmv4_context_t m_context; + uint8_t m_IS; //!< IS value at time of generation of packet. }; inline TrcStackElemCtxt::TrcStackElemCtxt(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) : @@ -188,6 +230,7 @@ class TrcStackElemAtom : public TrcStackElem const ocsd_atm_val commitOldest(); int cancelNewest(const int nCancel); + void mispredictNewest(); const bool isEmpty() const { return (m_atom.num == 0); }; private: @@ -217,6 +260,16 @@ inline int TrcStackElemAtom::cancelNewest(const int nCancel) return nRemove; } +// mispredict newest - flip the bit of the newest atom +inline void TrcStackElemAtom::mispredictNewest() +{ + uint32_t mask = 0x1 << (m_atom.num - 1); + if (m_atom.En_bits & mask) + m_atom.En_bits &= ~mask; + else + m_atom.En_bits |= mask; +} + /************************************************************/ /** Generic param element */ @@ -252,12 +305,20 @@ class EtmV4P0Stack void push_front(TrcStackElem *pElem); void push_back(TrcStackElem *pElem); // insert element when processing - void pop_back(); + void pop_back(bool pend_delete = true); + void pop_front(bool pend_delete = true); TrcStackElem *back(); + TrcStackElem *front(); size_t size(); + // iterate through stack from front + void from_front_init(); + TrcStackElem *from_front_next(); + void erase_curr_from_front(); // erase the element last returned + void delete_all(); void delete_back(); + void delete_front(); void delete_popped(); // creation functions - create and push if successful. @@ -265,13 +326,13 @@ class EtmV4P0Stack TrcStackElem *createParamElemNoParam(const p0_elem_t p0_type, const bool isP0, const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, bool back = false); TrcStackElemAtom *createAtomElem (const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const ocsd_pkt_atom &atom); TrcStackElemExcept *createExceptElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const bool bSame, const uint16_t excepNum); - TrcStackElemCtxt *createContextElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const etmv4_context_t &context); + 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); private: std::deque m_P0_stack; //!< P0 decode element stack std::vector m_popped_elem; //!< save list of popped but not deleted elements. - + std::deque::iterator m_iter; //!< iterate across the list w/o removing stuff }; inline EtmV4P0Stack::~EtmV4P0Stack() @@ -293,12 +354,20 @@ inline void EtmV4P0Stack::push_back(TrcStackElem *pElem) } // pop last element pointer off the stack and stash it for later deletion -inline void EtmV4P0Stack::pop_back() +inline void EtmV4P0Stack::pop_back(bool pend_delete /* = true */) { - m_popped_elem.push_back(m_P0_stack.back()); + if (pend_delete) + m_popped_elem.push_back(m_P0_stack.back()); m_P0_stack.pop_back(); } +inline void EtmV4P0Stack::pop_front(bool pend_delete /* = true */) +{ + if (pend_delete) + m_popped_elem.push_back(m_P0_stack.front()); + m_P0_stack.pop_front(); +} + // pop last element pointer off the stack and delete immediately inline void EtmV4P0Stack::delete_back() { @@ -310,12 +379,30 @@ inline void EtmV4P0Stack::delete_back() } } +// pop first element pointer off the stack and delete immediately +inline void EtmV4P0Stack::delete_front() +{ + if (m_P0_stack.size() > 0) + { + TrcStackElem* pElem = m_P0_stack.front(); + delete pElem; + m_P0_stack.pop_front(); + } +} + + + // get a pointer to the last element on the stack inline TrcStackElem *EtmV4P0Stack::back() { return m_P0_stack.back(); } +inline TrcStackElem *EtmV4P0Stack::front() +{ + return m_P0_stack.front(); +} + // remove and delete all the elements left on the stack inline void EtmV4P0Stack::delete_all() { 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 1c06e5ddf03a..419cd828928c 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 @@ -40,6 +40,7 @@ #include "opencsd/etmv4/trc_cmp_cfg_etmv4.h" #include "common/trc_gen_elem.h" #include "common/trc_ret_stack.h" +#include "common/ocsd_gen_elem_stack.h" #include "opencsd/etmv4/trc_etmv4_stack_elem.h" class TrcStackElem; @@ -65,35 +66,69 @@ class TrcPktDecodeEtmV4I : public TrcPktDecodeBase /* local decode methods */ void initDecoder(); // initial state on creation (zeros all config) void resetDecoder(); // reset state to start of decode. (moves state, retains config) + virtual void onFirstInitOK(); // override to set init related info. - ocsd_datapath_resp_t decodePacket(bool &Complete); // return true to indicate decode complete - can change FSM to commit state - return is false. - ocsd_datapath_resp_t commitElements(bool &Complete); // commit elements - may get wait response, or flag completion. - ocsd_datapath_resp_t flushEOT(); + ocsd_err_t decodePacket(); // decode packet into trace elements. return true to indicate decode complete - can change FSM to commit state - return is false. + ocsd_datapath_resp_t resolveElements(); // commit/cancel trace elements generated from latest / prior packets & send to output - may get wait response, or flag completion. + ocsd_err_t commitElements(); // commit elements - process element stack to generate output packets. + ocsd_err_t commitElemOnEOT(); + ocsd_err_t cancelElements(); // cancel elements. These not output + ocsd_err_t mispredictAtom(); // mispredict an atom + ocsd_err_t discardElements(); // discard elements and flush void doTraceInfoPacket(); - void updateContext(TrcStackElemCtxt *pCtxtElem); + void updateContext(TrcStackElemCtxt *pCtxtElem, OcsdTraceElement &elem); - // process atom will output instruction trace, or no memory access trace elements. - ocsd_datapath_resp_t processAtom(const ocsd_atm_val, bool &bCont); + // process atom will create instruction trace, or no memory access trace output elements. + ocsd_err_t processAtom(const ocsd_atm_val atom); // process an exception element - output instruction trace + exception generic type. - ocsd_datapath_resp_t processException(); + ocsd_err_t processException(); + + // process Q element + ocsd_err_t processQElement(); + + // process an element that cannot be cancelled / discarded + ocsd_err_t processTS_CC_EventElem(TrcStackElem *pElem); // process a bad packet - ocsd_datapath_resp_t handleBadPacket(const char *reason); + ocsd_err_t handleBadPacket(const char *reason); - ocsd_datapath_resp_t outputCC(TrcStackElemParam *pParamElem); - ocsd_datapath_resp_t outputTS(TrcStackElemParam *pParamElem, bool withCC); - ocsd_datapath_resp_t outputEvent(TrcStackElemParam *pParamElem); + ocsd_err_t addElemCC(TrcStackElemParam *pParamElem); + ocsd_err_t addElemTS(TrcStackElemParam *pParamElem, bool withCC); + ocsd_err_t addElemEvent(TrcStackElemParam *pParamElem); private: void SetInstrInfoInAddrISA(const ocsd_vaddr_t addr_val, const uint8_t isa); + const ocsd_isa calcISA(const bool SF, const uint8_t IS) const + { + if (SF) + return ocsd_isa_aarch64; + return (IS == 0) ? ocsd_isa_arm : ocsd_isa_thumb2; + } + typedef enum { + WP_NOT_FOUND, + WP_FOUND, + WP_NACC + } WP_res_t; - ocsd_err_t traceInstrToWP(bool &bWPFound, const bool traceToAddrNext = false, const ocsd_vaddr_t nextAddrMatch = 0); //!< follow instructions from the current address to a WP. true if good, false if memory cannot be accessed. + typedef struct { + ocsd_vaddr_t st_addr; + ocsd_vaddr_t en_addr; + uint32_t num_instr; + } instr_range_t; - ocsd_datapath_resp_t returnStackPop(); // pop return stack and update instruction address. + //!< follow instructions from the current address to a WP. true if good, false if memory cannot be accessed. + ocsd_err_t traceInstrToWP(instr_range_t &instr_range, WP_res_t &WPRes, const bool traceToAddrNext = false, const ocsd_vaddr_t nextAddrMatch = 0); - ocsd_datapath_resp_t outputTraceRange(const bool executed, ocsd_trc_index_t index); + inline const bool WPFound(WP_res_t res) const { return (res == WP_FOUND); }; + inline const bool WPNacc(WP_res_t res) const { return (res == WP_NACC); }; + + 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); + + ocsd_mem_space_acc_t getCurrMemSpace(); //** intra packet state (see ETMv4 spec 6.2.1); @@ -105,14 +140,18 @@ class TrcPktDecodeEtmV4I : public TrcPktDecodeBase uint32_t m_vmid_id; // most recent VMID bool m_is_secure; // true if Secure bool m_is_64bit; // true if 64 bit + uint8_t m_last_IS; // last instruction set value from address packet. // cycle counts int m_cc_threshold; - // speculative trace (unsupported at present in the decoder). + // speculative trace int m_curr_spec_depth; - int m_max_spec_depth; - + int m_max_spec_depth; // nax depth - from ID reg, beyond which auto-commit occurs + int m_unseen_spec_elem; // speculative elements at decode start + +/** Remove elements that are associated with data trace */ +#ifdef DATA_TRACE_SUPPORTED // data trace associative elements (unsupported at present in the decoder). int m_p0_key; int m_p0_key_max; @@ -121,6 +160,7 @@ class TrcPktDecodeEtmV4I : public TrcPktDecodeBase int m_cond_c_key; int m_cond_r_key; int m_cond_key_max_incr; +#endif uint8_t m_CSID; //!< Coresight trace ID for this decoder. @@ -134,55 +174,52 @@ class TrcPktDecodeEtmV4I : public TrcPktDecodeBase WAIT_SYNC, //!< waiting for sync packet. WAIT_TINFO, //!< waiting for trace info packet. DECODE_PKTS, //!< processing packets - creating decode elements on stack - COMMIT_ELEM, //!< commit elements for execution - create generic trace elements and pass on. + RESOLVE_ELEM, //!< analyze / resolve decode elements - create generic trace elements and pass on. } processor_state_t; processor_state_t m_curr_state; + unsync_info_t m_unsync_eot_info; //!< addition info when / why unsync / eot //** P0 element stack EtmV4P0Stack m_P0_stack; //!< P0 decode element stack - int m_P0_commit; //!< number of elements to commit + // element resolution + struct { + int P0_commit; //!< number of elements to commit + int P0_cancel; //!< elements to cancel + bool mispredict; //!< mispredict latest atom + bool discard; //!< discard elements + } m_elem_res; + + //! true if any of the element resolution fields are non-zero + const bool isElemForRes() const { + return (m_elem_res.P0_commit || m_elem_res.P0_cancel || + m_elem_res.mispredict || m_elem_res.discard); + } + + void clearElemRes() { + m_elem_res.P0_commit = 0; + m_elem_res.P0_cancel = 0; + m_elem_res.mispredict = false; + m_elem_res.discard = false; + } // packet decode state bool m_need_ctxt; //!< need context to continue bool m_need_addr; //!< need an address to continue - bool m_except_pending_addr; //!< next address packet is part of exception. - - // exception packet processing state (may need excep elem only, range+excep, range+ - typedef enum { - EXCEP_POP, // start of processing read exception packets off the stack and analyze - EXCEP_RANGE, // output a range element - EXCEP_NACC, // output a nacc element - EXCEP_CTXT, // output a ctxt element - EXCEP_EXCEP, // output an ecxeption element. - } excep_proc_state_t; - - struct { - excep_proc_state_t proc; //!< state of exception processing - etmv4_addr_val_t addr; //!< excetion return address. - uint32_t number; //!< exception number. - ocsd_trc_index_t index; //!< trace index for exception element - bool addr_b_tgt; //!< return address is also branch tgt address. - } m_excep_info; //!< exception info when processing exception packets + bool m_elem_pending_addr; //!< next address packet is needed for prev element. ocsd_instr_info m_instr_info; //!< instruction info for code follower - in address is the next to be decoded. - bool m_mem_nacc_pending; //!< need to output a memory access failure packet - ocsd_vaddr_t m_nacc_addr; //!< record unaccessible address - - ocsd_pe_context m_pe_context; //!< current context information etmv4_trace_info_t m_trace_info; //!< trace info for this trace run. bool m_prev_overflow; - bool m_flush_EOT; //!< true if doing an end of trace flush - cleans up lingering events / TS / CC - - TrcAddrReturnStack m_return_stack; - -//** output element - OcsdTraceElement m_output_elem; + TrcAddrReturnStack m_return_stack; //!< the address return stack. +//** output element handling + OcsdGenElemStack m_out_elem; //!< output element stack. + OcsdTraceElement &outElem() { return m_out_elem.getCurrElem(); }; //!< current out element }; #endif // ARM_TRC_PKT_DECODE_ETMV4I_H_INCLUDED diff --git a/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4d.h b/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4d.h deleted file mode 100644 index bb6a0029c0c0..000000000000 --- a/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4d.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * \file trc_pkt_elem_etmv4d.h - * \brief OpenCSD : - * - * \copyright Copyright (c) 2015, 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_ELEM_ETMV4D_H_INCLUDED -#define ARM_TRC_PKT_ELEM_ETMV4D_H_INCLUDED - -#include "trc_pkt_types_etmv4.h" -#include "common/trc_printable_elem.h" -#include "common/trc_pkt_elem_base.h" - -/** @addtogroup trc_pkts -@{*/ -/*! - * @class EtmV4DTrcPacket - * @brief ETMv4 Data Trace Protocol Packet . - * - * This class represents a single ETMv4 instruction trace packet, along with intra packet state. - * - */ -class EtmV4DTrcPacket : public TrcPacketBase, public ocsd_etmv4_d_pkt, trcPrintableElem -{ -public: - EtmV4DTrcPacket(); - ~EtmV4DTrcPacket(); - - // update interface - set packet values - - - - // packet status interface - get packet info. - - - // printing - virtual void toString(std::string &str) const; - virtual void toStringFmt(const uint32_t fmtFlags, std::string &str) const; -}; - -/** @}*/ - -#endif // ARM_TRC_PKT_ELEM_ETMV4D_H_INCLUDED - -/* End of File trc_pkt_elem_etmv4d.h */ 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 02adfc51aa75..8ccf36b373db 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 @@ -57,14 +57,7 @@ class Etmv4PktAddrStack public: Etmv4PktAddrStack() { - for (int i = 0; i < 3; i++) - { - m_v_addr[i].pkt_bits = 0; - m_v_addr[i].size = VA_64BIT; - m_v_addr[i].val = 0; - m_v_addr[i].valid_bits = 0; - m_v_addr_ISA[i] = 0; - } + reset_stack(); } ~Etmv4PktAddrStack() {}; @@ -87,6 +80,20 @@ class Etmv4PktAddrStack } } + // explicit reset for TInfo. + void reset_stack() + { + for (int i = 0; i < 3; i++) + { + m_v_addr[i].pkt_bits = 0; + m_v_addr[i].size = OCSD_MAX_VA_BITSIZE == 64 ? VA_64BIT : VA_32BIT; + m_v_addr[i].val = 0; + m_v_addr[i].valid_bits = OCSD_MAX_VA_BITSIZE; + m_v_addr_ISA[i] = 0; + } + + } + private: ocsd_pkt_vaddr m_v_addr[3]; //!< most recently broadcast address packet uint8_t m_v_addr_ISA[3]; @@ -172,6 +179,7 @@ class EtmV4ITrcPacket : public TrcPacketBase, public ocsd_etmv4_i_pkt, public t // atom const ocsd_pkt_atom &getAtom() const { return atom; }; + const int getNumAtoms() const { return atom.num; }; // context const etmv4_context_t &getContext() const { return context; }; @@ -188,6 +196,10 @@ class EtmV4ITrcPacket : public TrcPacketBase, public ocsd_etmv4_i_pkt, public t // cc const uint32_t getCC() const { return pkt_valid.bits.cc_valid ? cycle_count : 0; }; + // speculation + const int getCommitElem() const { return commit_elements; }; + const int getCancelElem() const { return cancel_elements; }; + // packet type const bool isBadPacket() const; @@ -227,6 +239,10 @@ inline void EtmV4ITrcPacket::clearTraceInfo() // set these as defaults - if they don't appear in TINFO this is the state. setTraceInfo(0); setTraceInfoSpec(0); + + // explicitly reset the stack & zero the current address. + m_addr_stack.reset_stack(); + m_addr_stack.get_idx(0, v_addr, v_addr_ISA); } inline void EtmV4ITrcPacket::setTraceInfo(const uint32_t infoVal) @@ -450,17 +466,17 @@ inline void EtmV4ITrcPacket::set32BitAddress(const uint32_t addr, const uint8_t if (pkt_valid.bits.context_valid && context.SF) { v_addr.size = VA_64BIT; - if (v_addr.valid_bits < 32) // may be updating a 64 bit address so only set 32 if currently less. - v_addr.valid_bits = 32; v_addr.val = (v_addr.val & ~mask) | (addr & mask); } else { v_addr.val = addr; v_addr.size = VA_32BIT; - v_addr.valid_bits = 32; } - + + if (v_addr.valid_bits < 32) // may be updating a 64 bit address so only set 32 if currently less. + v_addr.valid_bits = 32; + v_addr_ISA = IS; push_vaddr(); } diff --git a/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4.h b/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4.h index 0d9ccea2be54..25bdf5109558 100644 --- a/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4.h +++ b/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4.h @@ -35,70 +35,13 @@ #ifndef ARM_TRC_PKT_PROC_ETMV4_H_INCLUDED #define ARM_TRC_PKT_PROC_ETMV4_H_INCLUDED +// split I & D into separate files, retain this header for backward compatibility +// for now just include the I packet processor as that is the only one implemented. #include "trc_pkt_types_etmv4.h" +#include "trc_pkt_proc_etmv4i.h" #include "common/trc_pkt_proc_base.h" -class EtmV4IPktProcImpl; /**< ETMv4 I channel packet processor */ -class EtmV4DPktProcImpl; /**< ETMv4 D channel packet processor */ -class EtmV4ITrcPacket; -class EtmV4DTrcPacket; -class EtmV4Config; - -/** @addtogroup ocsd_pkt_proc -@{*/ - -class TrcPktProcEtmV4I : public TrcPktProcBase< EtmV4ITrcPacket, ocsd_etmv4_i_pkt_type, EtmV4Config> -{ -public: - TrcPktProcEtmV4I(); - TrcPktProcEtmV4I(int instIDNum); - virtual ~TrcPktProcEtmV4I(); - -protected: - /* implementation packet processing interface */ - virtual ocsd_datapath_resp_t processData( const ocsd_trc_index_t index, - const uint32_t dataBlockSize, - const uint8_t *pDataBlock, - uint32_t *numBytesProcessed); - virtual ocsd_datapath_resp_t onEOT(); - virtual ocsd_datapath_resp_t onReset(); - virtual ocsd_datapath_resp_t onFlush(); - virtual ocsd_err_t onProtocolConfig(); - virtual const bool isBadPacket() const; - - friend class EtmV4IPktProcImpl; - - EtmV4IPktProcImpl *m_pProcessor; -}; - - -class TrcPktProcEtmV4D : public TrcPktProcBase< EtmV4DTrcPacket, ocsd_etmv4_d_pkt_type, EtmV4Config> -{ -public: - TrcPktProcEtmV4D(); - TrcPktProcEtmV4D(int instIDNum); - virtual ~TrcPktProcEtmV4D(); - -protected: - /* implementation packet processing interface */ - virtual ocsd_datapath_resp_t processData( const ocsd_trc_index_t index, - const uint32_t dataBlockSize, - const uint8_t *pDataBlock, - uint32_t *numBytesProcessed); - virtual ocsd_datapath_resp_t onEOT(); - virtual ocsd_datapath_resp_t onReset(); - virtual ocsd_datapath_resp_t onFlush(); - virtual ocsd_err_t onProtocolConfig(); - virtual const bool isBadPacket() const; - - friend class EtmV4DPktProcImpl; - - EtmV4DPktProcImpl *m_pProcessor; -}; - -/** @}*/ - #endif // ARM_TRC_PKT_PROC_ETMV4_H_INCLUDED /* End of File trc_pkt_proc_etmv4.h */ diff --git a/contrib/opencsd/decoder/source/etmv4/trc_pkt_proc_etmv4i_impl.h b/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4i.h similarity index 82% rename from contrib/opencsd/decoder/source/etmv4/trc_pkt_proc_etmv4i_impl.h rename to contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4i.h index 429f32711f3e..abc322654b8d 100644 --- a/contrib/opencsd/decoder/source/etmv4/trc_pkt_proc_etmv4i_impl.h +++ b/contrib/opencsd/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4i.h @@ -1,8 +1,8 @@ /* - * \file trc_pkt_proc_etmv4i_impl.h + * \file trc_pkt_proc_etmv4i.h * \brief OpenCSD : Implementation of ETMv4 packet processing * - * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + * \copyright Copyright (c) 2015, 2019 ARM Limited. All Rights Reserved. */ /* @@ -35,54 +35,37 @@ #ifndef ARM_TRC_PKT_PROC_ETMV4I_IMPL_H_INCLUDED #define ARM_TRC_PKT_PROC_ETMV4I_IMPL_H_INCLUDED +#include "trc_pkt_types_etmv4.h" #include "opencsd/etmv4/trc_pkt_proc_etmv4.h" #include "opencsd/etmv4/trc_cmp_cfg_etmv4.h" #include "opencsd/etmv4/trc_pkt_elem_etmv4i.h" +#include "common/trc_raw_buffer.h" +#include "common/trc_pkt_proc_base.h" -class TraceRawBuffer +class EtmV4ITrcPacket; +class EtmV4Config; + +/** @addtogroup ocsd_pkt_proc +@{*/ + +class TrcPktProcEtmV4I : public TrcPktProcBase< EtmV4ITrcPacket, ocsd_etmv4_i_pkt_type, EtmV4Config> { public: - TraceRawBuffer(); - ~TraceRawBuffer() {}; + TrcPktProcEtmV4I(); + TrcPktProcEtmV4I(int instIDNum); + virtual ~TrcPktProcEtmV4I(); - // init the buffer - void init(const uint32_t size, const uint8_t *rawtrace, std::vector *out_packet); - void copyByteToPkt(); // move a byte to the packet buffer - uint8_t peekNextByte(); // value of next byte in buffer. - - bool empty() { return m_bufProcessed == m_bufSize; }; - // bytes processed. - uint32_t processed() { return m_bufProcessed; }; - // buffer size; - uint32_t size() { return m_bufSize; } - -private: - uint32_t m_bufSize; - uint32_t m_bufProcessed; - const uint8_t *m_pBuffer; - std::vector *pkt; - -}; - -class EtmV4IPktProcImpl -{ -public: - EtmV4IPktProcImpl(); - ~EtmV4IPktProcImpl(); - - void Initialise(TrcPktProcEtmV4I *p_interface); - - ocsd_err_t Configure(const EtmV4Config *p_config); - - - ocsd_datapath_resp_t processData( const ocsd_trc_index_t index, +protected: + /* implementation packet processing interface */ + virtual ocsd_datapath_resp_t processData( const ocsd_trc_index_t index, const uint32_t dataBlockSize, const uint8_t *pDataBlock, uint32_t *numBytesProcessed); - ocsd_datapath_resp_t onEOT(); - ocsd_datapath_resp_t onReset(); - ocsd_datapath_resp_t onFlush(); - const bool isBadPacket() const; + virtual ocsd_datapath_resp_t onEOT(); + virtual ocsd_datapath_resp_t onReset(); + virtual ocsd_datapath_resp_t onFlush(); + virtual ocsd_err_t onProtocolConfig(); + virtual const bool isBadPacket() const; protected: typedef enum _process_state { @@ -100,7 +83,6 @@ class EtmV4IPktProcImpl /** packet processor configuration **/ bool m_isInit; - TrcPktProcEtmV4I *m_interface; /**< The interface to the other decode components */ // etmv4 hardware configuration EtmV4Config m_config; @@ -111,7 +93,6 @@ class EtmV4IPktProcImpl int m_currPktIdx; // index into raw packet when expanding EtmV4ITrcPacket m_curr_packet; // expanded packet ocsd_trc_index_t m_packet_index; // index of the start of the current packet -// uint32_t m_blockBytesProcessed; // number of bytes processed in the current data block ocsd_trc_index_t m_blockIndex; // index at the start of the current data block being processed // searching for sync @@ -207,7 +188,7 @@ class EtmV4IPktProcImpl int extractShortAddr(const std::vector &buffer, const int st_idx, const uint8_t IS, uint32_t &value, int &bits); // packet processing is table driven. - typedef void (EtmV4IPktProcImpl::*PPKTFN)(uint8_t); + typedef void (TrcPktProcEtmV4I::*PPKTFN)(uint8_t); PPKTFN m_pIPktFn; struct _pkt_i_table_t { @@ -221,11 +202,13 @@ class EtmV4IPktProcImpl }; -inline const bool EtmV4IPktProcImpl::isBadPacket() const +inline const bool TrcPktProcEtmV4I::isBadPacket() const { return m_curr_packet.isBadPacket(); } +/** @}*/ + #endif // ARM_TRC_PKT_PROC_ETMV4I_IMPL_H_INCLUDED /* End of File trc_pkt_proc_etmv4i_impl.h */ 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 dd69a4bf6778..7e98050c77c4 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 @@ -85,7 +85,8 @@ typedef enum _ocsd_etmv4_i_pkt_type // speculation ETM4_PKT_I_COMMIT = 0x2D, /*!< b00101101 */ - ETM4_PKT_I_CANCEL_F1 = 0x2E, /*!< b0010111x */ + ETM4_PKT_I_CANCEL_F1 = 0x2E, /*!< b00101110 */ + ETM4_PKT_I_CANCEL_F1_MISPRED = 0x2F, /*!< b00101111 */ ETM4_PKT_I_MISPREDICT = 0x30, /*!< b001100xx */ ETM4_PKT_I_CANCEL_F2 = 0x34, /*!< b001101xx */ ETM4_PKT_I_CANCEL_F3 = 0x38, /*!< b00111xxx */ diff --git a/contrib/opencsd/decoder/include/opencsd/ocsd_if_types.h b/contrib/opencsd/decoder/include/opencsd/ocsd_if_types.h index 7d74d77c240b..23087ee694b1 100644 --- a/contrib/opencsd/decoder/include/opencsd/ocsd_if_types.h +++ b/contrib/opencsd/decoder/include/opencsd/ocsd_if_types.h @@ -273,11 +273,11 @@ typedef enum _ocsd_dcd_tree_src_t { /** Core Architecture Version */ typedef enum _ocsd_arch_version { - ARCH_UNKNOWN, /**< unknown architecture */ - ARCH_CUSTOM, /**< None ARM, custom architecture */ - ARCH_V7, /**< V7 architecture */ - ARCH_V8, /**< V8 architecture */ - ARCH_V8r3, /**< V8.3 architecture */ + ARCH_UNKNOWN = 0x0000, /**< unknown architecture */ + ARCH_CUSTOM = 0x0001, /**< None ARM, custom architecture */ + ARCH_V7 = 0x0700, /**< V7 architecture */ + ARCH_V8 = 0x0800, /**< V8 architecture */ + ARCH_V8r3 = 0x0803, /**< V8.3 architecture */ } ocsd_arch_version_t; // macros for arch version comparisons. @@ -430,9 +430,10 @@ typedef enum _ocsd_mem_space_acc_t { OCSD_MEM_SPACE_EL1N = 0x2, /**< NS EL1/0 */ OCSD_MEM_SPACE_EL2 = 0x4, /**< NS EL2 */ OCSD_MEM_SPACE_EL3 = 0x8, /**< S EL3 */ - OCSD_MEM_SPACE_S = 0x9, /**< Any S */ + OCSD_MEM_SPACE_EL2S = 0x10, /**< S EL2 */ + OCSD_MEM_SPACE_S = 0x19, /**< Any S */ OCSD_MEM_SPACE_N = 0x6, /**< Any NS */ - OCSD_MEM_SPACE_ANY = 0xF, /**< Any sec level / EL - live system use current EL + sec state */ + OCSD_MEM_SPACE_ANY = 0x1F, /**< Any sec level / EL - live system use current EL + sec state */ } ocsd_mem_space_acc_t; /** @@ -494,13 +495,14 @@ typedef struct _ocsd_file_mem_region { /** @name Packet Processor Operation Control Flags common operational flags - bottom 16 bits, - component specific - top 16 bits. + protocol component specific - top 16 bits. + (common flags share bitfield with pkt decoder common flags and create flags) @{*/ -#define OCSD_OPFLG_PKTPROC_NOFWD_BAD_PKTS 0x00000001 /**< don't forward bad packets up data path */ -#define OCSD_OPFLG_PKTPROC_NOMON_BAD_PKTS 0x00000002 /**< don't forward bad packets to monitor interface */ -#define OCSD_OPFLG_PKTPROC_ERR_BAD_PKTS 0x00000004 /**< throw error for bad packets - halt decoding. */ -#define OCSD_OPFLG_PKTPROC_UNSYNC_ON_BAD_PKTS 0x00000008 /**< switch to unsynced state on bad packets - wait for next sync point */ +#define OCSD_OPFLG_PKTPROC_NOFWD_BAD_PKTS 0x00000010 /**< don't forward bad packets up data path */ +#define OCSD_OPFLG_PKTPROC_NOMON_BAD_PKTS 0x00000020 /**< don't forward bad packets to monitor interface */ +#define OCSD_OPFLG_PKTPROC_ERR_BAD_PKTS 0x00000040 /**< throw error for bad packets - halt decoding. */ +#define OCSD_OPFLG_PKTPROC_UNSYNC_ON_BAD_PKTS 0x00000080 /**< switch to unsynced state on bad packets - wait for next sync point */ /** mask to combine all common packet processor operational control flags */ #define OCSD_OPFLG_PKTPROC_COMMON (OCSD_OPFLG_PKTPROC_NOFWD_BAD_PKTS | \ @@ -508,14 +510,18 @@ typedef struct _ocsd_file_mem_region { OCSD_OPFLG_PKTPROC_ERR_BAD_PKTS | \ OCSD_OPFLG_PKTPROC_UNSYNC_ON_BAD_PKTS ) +/** mask for the component spcific flags */ +#define OCSD_OPFLG_COMP_MODE_MASK 0xFFFF0000 + /** @}*/ /** @name Packet Decoder Operation Control Flags common operational flags - bottom 16 bits, - component specific - top 16 bits. -@{*/ + protcol component specific - top 16 bits. + (common flags share bitfield with pkt processor common flags and create flags) + @{*/ -#define OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS 0x00000001 /**< 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 unsync and wait) */ /** mask to combine all common packet processor operational control flags */ #define OCSD_OPFLG_PKTDEC_COMMON (OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS) @@ -524,7 +530,8 @@ typedef struct _ocsd_file_mem_region { /** @name Decoder creation information - Flags to use when creating decoders by name + Flags to use when creating decoders by name. + - share bitfield with pkt processor flags and packet decoder common flags. Builtin decoder names. diff --git a/contrib/opencsd/decoder/include/opencsd/ocsd_if_version.h b/contrib/opencsd/decoder/include/opencsd/ocsd_if_version.h index 70c8df41f52b..38baa02e8b48 100644 --- a/contrib/opencsd/decoder/include/opencsd/ocsd_if_version.h +++ b/contrib/opencsd/decoder/include/opencsd/ocsd_if_version.h @@ -43,8 +43,8 @@ /** @name Library Versioning @{*/ #define OCSD_VER_MAJOR 0x0 /**< Library Major Version */ -#define OCSD_VER_MINOR 0xC /**< Library Minor Version */ -#define OCSD_VER_PATCH 0x0 /**< Library Patch Version */ +#define OCSD_VER_MINOR 0xE /**< Library Minor Version */ +#define OCSD_VER_PATCH 0x2 /**< 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.12.0" /**< Library Version string */ +#define OCSD_VER_STRING "0.14.2" /**< 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/ptm/trc_pkt_decode_ptm.h b/contrib/opencsd/decoder/include/opencsd/ptm/trc_pkt_decode_ptm.h index 395b316cda06..f9e1abe4ebc3 100644 --- a/contrib/opencsd/decoder/include/opencsd/ptm/trc_pkt_decode_ptm.h +++ b/contrib/opencsd/decoder/include/opencsd/ptm/trc_pkt_decode_ptm.h @@ -154,6 +154,7 @@ class TrcPktDecodePtm : public TrcPktDecodeBase } processor_state_t; processor_state_t m_curr_state; + unsync_info_t m_unsync_info; const bool processStateIsCont() const; diff --git a/contrib/opencsd/decoder/include/opencsd/stm/trc_pkt_decode_stm.h b/contrib/opencsd/decoder/include/opencsd/stm/trc_pkt_decode_stm.h index a4807207eb1e..bd29cafa799f 100644 --- a/contrib/opencsd/decoder/include/opencsd/stm/trc_pkt_decode_stm.h +++ b/contrib/opencsd/decoder/include/opencsd/stm/trc_pkt_decode_stm.h @@ -79,6 +79,7 @@ class TrcPktDecodeStm : public TrcPktDecodeBase } processor_state_t; processor_state_t m_curr_state; + unsync_info_t m_unsync_info; ocsd_swt_info_t m_swt_packet_info; 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 1d77b53cf8f9..1a285a064b63 100644 --- a/contrib/opencsd/decoder/include/opencsd/trc_gen_elem_types.h +++ b/contrib/opencsd/decoder/include/opencsd/trc_gen_elem_types.h @@ -52,6 +52,7 @@ typedef enum _ocsd_gen_trc_elem_t OCSD_GEN_TRC_ELEM_EO_TRACE, /*!< end of the available trace in the buffer. */ OCSD_GEN_TRC_ELEM_PE_CONTEXT, /*!< PE status update / change (arch, ctxtid, vmid etc). */ OCSD_GEN_TRC_ELEM_INSTR_RANGE, /*!< traced N consecutive instructions from addr (no intervening events or data elements), may have data assoc key */ + OCSD_GEN_TRC_ELEM_I_RANGE_NOPATH, /*!< traced N instructions in a range, but incomplete information as to program execution path from start to end of range */ OCSD_GEN_TRC_ELEM_ADDR_NACC, /*!< tracing in inaccessible memory area */ OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN, /*!< address currently unknown - need address packet update */ OCSD_GEN_TRC_ELEM_EXCEPTION, /*!< exception - start address may be exception target, end address may be preferred ret addr. */ @@ -75,6 +76,16 @@ typedef struct _trace_event_t { uint16_t ev_number; /**< event number if numbered event type */ } trace_event_t; +typedef enum _unsync_info_t { + UNSYNC_UNKNOWN, /**< unknown /undefined */ + UNSYNC_INIT_DECODER, /**< decoder intialisation - start of trace. */ + UNSYNC_RESET_DECODER, /**< decoder reset. */ + UNSYNC_OVERFLOW, /**< overflow packet - need to re-sync / end of trace after overflow. */ + UNSYNC_DISCARD, /**< specl trace discard - need to re-sync. */ + UNSYNC_BAD_PACKET, /**< bad packet at input - resync to restart. */ + UNSYNC_EOT, /**< end of trace - no additional info */ +} unsync_info_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 */ @@ -110,6 +121,7 @@ typedef struct _ocsd_generic_trace_elem { trace_on_reason_t trace_on_reason; /**< reason for the trace on packet */ 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. */ }; const void *ptr_extended_data; /**< pointer to extended data buffer (data trace, sw trace payload) / custom structure */ diff --git a/contrib/opencsd/decoder/include/pkt_printers/pkt_printer_t.h b/contrib/opencsd/decoder/include/pkt_printers/pkt_printer_t.h index 9eb37f4e2833..c00daa1f64d3 100644 --- a/contrib/opencsd/decoder/include/pkt_printers/pkt_printer_t.h +++ b/contrib/opencsd/decoder/include/pkt_printers/pkt_printer_t.h @@ -102,7 +102,7 @@ template ocsd_datapath_resp_t PacketPrinter

::PacketDataIn( const ocs if(!m_bRawPrint && (m_last_resp == OCSD_RESP_WAIT)) { // expect a flush or a complete reset after a wait. - if((op != OCSD_OP_FLUSH) || (op != OCSD_OP_RESET)) + if((op != OCSD_OP_FLUSH) && (op != OCSD_OP_RESET)) { m_oss <<"ID:"<< std::hex << (uint32_t)m_trcID << "\tERROR: FLUSH operation expected after wait on trace decode path\n"; itemPrintLine(m_oss.str()); diff --git a/contrib/opencsd/decoder/source/etmv3/trc_pkt_decode_etmv3.cpp b/contrib/opencsd/decoder/source/etmv3/trc_pkt_decode_etmv3.cpp index 0a15a33c42fb..e68a73fd9e0d 100644 --- a/contrib/opencsd/decoder/source/etmv3/trc_pkt_decode_etmv3.cpp +++ b/contrib/opencsd/decoder/source/etmv3/trc_pkt_decode_etmv3.cpp @@ -130,6 +130,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV3::onEOT() try { pElem = GetNextOpElem(resp); pElem->setType(OCSD_GEN_TRC_ELEM_EO_TRACE); + pElem->setUnSyncEOTReason(UNSYNC_EOT); m_outputElemList.commitAllPendElem(); m_curr_state = SEND_PKTS; resp = m_outputElemList.sendElements(); @@ -147,6 +148,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV3::onEOT() ocsd_datapath_resp_t TrcPktDecodeEtmV3::onReset() { ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + m_unsync_info = UNSYNC_RESET_DECODER; resetDecoder(); return resp; } @@ -199,6 +201,7 @@ void TrcPktDecodeEtmV3::initDecoder() { m_CSID = 0; resetDecoder(); + m_unsync_info = UNSYNC_INIT_DECODER; m_code_follower.initInterfaces(getMemoryAccessAttachPt(),getInstrDecodeAttachPt()); m_outputElemList.initSendIf(getTraceElemOutAttachPt()); } @@ -355,6 +358,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV3::decodePacket(bool &pktDone) catch(ocsdError &err) { LogError(err); + m_unsync_info = UNSYNC_BAD_PACKET; resetDecoder(); // mark decoder as unsynced - dump any current state. pktDone = true; } @@ -362,6 +366,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV3::decodePacket(bool &pktDone) { LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_FAIL,m_index_curr_pkt,m_CSID,"Bad Packet sequence.")); resp = OCSD_RESP_FATAL_SYS_ERR; + m_unsync_info = UNSYNC_BAD_PACKET; resetDecoder(); // mark decoder as unsynced - dump any current state. pktDone = true; } @@ -375,11 +380,13 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV3::sendUnsyncPacket() try { pElem = GetNextOpElem(resp); pElem->setType(OCSD_GEN_TRC_ELEM_NO_SYNC); + pElem->setUnSyncEOTReason(m_unsync_info); resp = m_outputElemList.sendElements(); } catch(ocsdError &err) { LogError(err); + m_unsync_info = UNSYNC_BAD_PACKET; resetDecoder(); // mark decoder as unsynced - dump any current state. } return resp; @@ -464,6 +471,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV3::processISync(const bool withCC, const bo catch(ocsdError &err) { LogError(err); + m_unsync_info = UNSYNC_BAD_PACKET; resetDecoder(); // mark decoder as unsynced - dump any current state. } return resp; @@ -531,6 +539,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV3::processBranchAddr() catch(ocsdError &err) { LogError(err); + m_unsync_info = UNSYNC_BAD_PACKET; resetDecoder(); // mark decoder as unsynced - dump any current state. } } @@ -647,6 +656,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV3::processPHdr() catch(ocsdError &err) { LogError(err); + m_unsync_info = UNSYNC_BAD_PACKET; resetDecoder(); // mark decoder as unsynced - dump any current state. } return resp; 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 8916c7dc350d..8e9ba9ac43ca 100644 --- a/contrib/opencsd/decoder/source/etmv4/trc_etmv4_stack_elem.cpp +++ b/contrib/opencsd/decoder/source/etmv4/trc_etmv4_stack_elem.cpp @@ -90,13 +90,17 @@ TrcStackElemExcept *EtmV4P0Stack::createExceptElem(const ocsd_etmv4_i_pkt_type r return pElem; } -TrcStackElemCtxt *EtmV4P0Stack::createContextElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const etmv4_context_t &context) +TrcStackElemCtxt *EtmV4P0Stack::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*/) { TrcStackElemCtxt *pElem = new (std::nothrow) TrcStackElemCtxt(root_pkt, root_index); if (pElem) { pElem->setContext(context); - push_front(pElem); + pElem->setIS(IS); + if (back) + push_back(pElem); + else + push_front(pElem); } return pElem; @@ -113,4 +117,40 @@ TrcStackElemAddr *EtmV4P0Stack::createAddrElem(const ocsd_etmv4_i_pkt_type root_ return pElem; } +TrcStackQElem *EtmV4P0Stack::createQElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const int count) +{ + TrcStackQElem *pElem = new (std::nothrow) TrcStackQElem(root_pkt, root_index); + if (pElem) + { + pElem->setInstrCount(count); + push_front(pElem); + } + return pElem; +} + +// iteration functions +void EtmV4P0Stack::from_front_init() +{ + m_iter = m_P0_stack.begin(); +} + +TrcStackElem *EtmV4P0Stack::from_front_next() +{ + TrcStackElem *pElem = 0; + if (m_iter != m_P0_stack.end()) + { + pElem = *m_iter++; + } + return pElem; +} + +void EtmV4P0Stack::erase_curr_from_front() +{ + std::deque::iterator erase_iter; + erase_iter = m_iter; + erase_iter--; + m_P0_stack.erase(erase_iter); +} + + /* End of file trc_etmv4_stack_elem.cpp */ 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 2eb6cbc3f5bf..393046ba23d1 100644 --- a/contrib/opencsd/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp +++ b/contrib/opencsd/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp @@ -5,7 +5,6 @@ * \copyright Copyright (c) 2015, 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: @@ -63,6 +62,7 @@ TrcPktDecodeEtmV4I::~TrcPktDecodeEtmV4I() ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processPacket() { ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + ocsd_err_t err = OCSD_OK; bool bPktDone = false; while(!bPktDone) @@ -71,9 +71,18 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processPacket() { case NO_SYNC: // output the initial not synced packet to the sink - m_output_elem.setType(OCSD_GEN_TRC_ELEM_NO_SYNC); - resp = outputTraceElement(m_output_elem); - m_curr_state = WAIT_SYNC; + err = m_out_elem.resetElemStack(); + if (!err) + err = m_out_elem.addElemType(m_index_curr_pkt, OCSD_GEN_TRC_ELEM_NO_SYNC); + if (!err) + { + outElem().setUnSyncEOTReason(m_unsync_eot_info); + resp = m_out_elem.sendElements(); + m_curr_state = WAIT_SYNC; + } + else + resp = OCSD_RESP_FATAL_SYS_ERR; + // fall through to check if the current packet is the async we are waiting for. break; @@ -96,13 +105,31 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processPacket() break; case DECODE_PKTS: - resp = decodePacket(bPktDone); // this may change the state to commit elem; + // this may change the state to RESOLVE_ELEM if required; + err = decodePacket(); + if (err) + { +#ifdef OCSD_WARN_UNSUPPORTED + if (err == OCSD_ERR_UNSUPP_DECODE_PKT) + resp = OCSD_RESP_WARN_CONT; + else +#else + resp = OCSD_RESP_FATAL_INVALID_DATA; +#endif + + bPktDone = true; + } + else if (m_curr_state != RESOLVE_ELEM) + bPktDone = true; break; - case COMMIT_ELEM: - resp = commitElements(bPktDone); // this will change the state to DECODE_PKTS once all elem committed. + case RESOLVE_ELEM: + // this will change the state to DECODE_PKTS once required elem resolved & + // needed generic packets output + resp = resolveElements(); + if ((m_curr_state == DECODE_PKTS) || (!OCSD_DATA_RESP_IS_CONT(resp))) + bPktDone = true; break; - } } return resp; @@ -111,14 +138,21 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processPacket() ocsd_datapath_resp_t TrcPktDecodeEtmV4I::onEOT() { ocsd_datapath_resp_t resp = OCSD_RESP_CONT; - m_flush_EOT = true; - resp = flushEOT(); + ocsd_err_t err; + if ((err = commitElemOnEOT()) != OCSD_OK) + { + resp = OCSD_RESP_FATAL_INVALID_DATA; + LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, "Error flushing element stack at end of trace data.")); + } + else + resp = m_out_elem.sendElements(); return resp; } ocsd_datapath_resp_t TrcPktDecodeEtmV4I::onReset() { ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + m_unsync_eot_info = UNSYNC_RESET_DECODER; resetDecoder(); return resp; } @@ -127,15 +161,10 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::onFlush() { ocsd_datapath_resp_t resp = OCSD_RESP_CONT; - // continue exception processing (can't go through processPacket as elements no longer on stack) - if(m_excep_info.proc != EXCEP_POP) - resp = processException(); - // continue ongoing output operations on comitted elements. - else if(m_curr_state == COMMIT_ELEM) - resp = processPacket(); - // continue flushing at end of trace - else if(m_flush_EOT) - resp = flushEOT(); + if (m_curr_state == RESOLVE_ELEM) + resp = resolveElements(); + else + resp = m_out_elem.sendElements(); return resp; } @@ -146,8 +175,14 @@ ocsd_err_t TrcPktDecodeEtmV4I::onProtocolConfig() // set some static config elements m_CSID = m_config->getTraceID(); m_max_spec_depth = m_config->MaxSpecDepth(); + + // elements associated with data trace +#ifdef DATA_TRACE_SUPPORTED m_p0_key_max = m_config->P0_Key_Max(); m_cond_key_max_incr = m_config->CondKeyMaxIncr(); +#endif + + m_out_elem.initCSID(m_CSID); // set up static trace instruction decode elements m_instr_info.dsb_dmb_waypoints = 0; @@ -168,12 +203,7 @@ ocsd_err_t TrcPktDecodeEtmV4I::onProtocolConfig() // check config compatible with current decoder support level. // at present no data trace, no spec depth, no return stack, no QE // Remove these checks as support is added. - if(m_max_spec_depth != 0) - { - err = OCSD_ERR_HW_CFG_UNSUPP; - LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : None-zero speculation depth not supported")); - } - else if(m_config->enabledDataTrace()) + if(m_config->enabledDataTrace()) { err = OCSD_ERR_HW_CFG_UNSUPP; LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : Data trace elements not supported")); @@ -188,15 +218,9 @@ ocsd_err_t TrcPktDecodeEtmV4I::onProtocolConfig() err = OCSD_ERR_HW_CFG_UNSUPP; LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : Trace on conditional non-branch elements not supported.")); } - else if(m_config->enabledQE()) - { - err = OCSD_ERR_HW_CFG_UNSUPP; - LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : Trace using Q elements not supported.")); - } return err; } - /************* local decode methods */ void TrcPktDecodeEtmV4I::initDecoder() { @@ -205,12 +229,17 @@ void TrcPktDecodeEtmV4I::initDecoder() /* init elements that get set by config */ m_max_spec_depth = 0; - m_p0_key_max = 0; m_CSID = 0; - m_cond_key_max_incr = 0; m_IASize64 = false; + // elements associated with data trace +#ifdef DATA_TRACE_SUPPORTED + m_p0_key_max = 0; + m_cond_key_max_incr = 0; +#endif + // reset decoder state to unsynced + m_unsync_eot_info = UNSYNC_INIT_DECODER; resetDecoder(); } @@ -224,30 +253,36 @@ void TrcPktDecodeEtmV4I::resetDecoder() m_is_64bit = false; m_cc_threshold = 0; m_curr_spec_depth = 0; + m_need_ctxt = true; + m_need_addr = true; + m_elem_pending_addr = false; + m_prev_overflow = false; + m_P0_stack.delete_all(); + m_out_elem.resetElemStack(); + m_last_IS = 0; + clearElemRes(); + + // elements associated with data trace +#ifdef DATA_TRACE_SUPPORTED m_p0_key = 0; m_cond_c_key = 0; m_cond_r_key = 0; - m_need_ctxt = true; - m_need_addr = true; - m_except_pending_addr = false; - m_mem_nacc_pending = false; - m_prev_overflow = false; - m_P0_stack.delete_all(); - m_output_elem.init(); - m_excep_info.proc = EXCEP_POP; - m_flush_EOT = false; +#endif } -// this function can output an immediate generic element if this covers the complete packet decode, -// or stack P0 and other elements for later processing on commit or cancel. -ocsd_datapath_resp_t TrcPktDecodeEtmV4I::decodePacket(bool &Complete) +void TrcPktDecodeEtmV4I::onFirstInitOK() { + // once init, set the output element interface to the out elem list. + m_out_elem.initSendIf(this->getTraceElemOutAttachPt()); +} + +// Changes a packet into stack of trace elements - these will be resolved and output later +ocsd_err_t TrcPktDecodeEtmV4I::decodePacket() +{ + ocsd_err_t err = OCSD_OK; bool bAllocErr = false; - ocsd_datapath_resp_t resp = OCSD_RESP_CONT; - Complete = true; bool is_addr = false; - bool is_except = false; - + switch(m_curr_packet_in->getType()) { case ETM4_PKT_I_ASYNC: // nothing to do with this packet. @@ -266,13 +301,6 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::decodePacket(bool &Complete) } break; - case ETM4_PKT_I_OVERFLOW: - { - if (m_P0_stack.createParamElemNoParam(P0_OVERFLOW, false, m_curr_packet_in->getType(), m_index_curr_pkt) == 0) - bAllocErr = true; - } - break; - case ETM4_PKT_I_ATOM_F1: case ETM4_PKT_I_ATOM_F2: case ETM4_PKT_I_ATOM_F3: @@ -289,7 +317,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::decodePacket(bool &Complete) case ETM4_PKT_I_CTXT: { - if (m_P0_stack.createContextElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getContext()) == 0) + if (m_P0_stack.createContextElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getContext(), m_last_IS) == 0) bAllocErr = true; } break; @@ -299,7 +327,8 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::decodePacket(bool &Complete) etmv4_addr_val_t addr; addr.val = m_curr_packet_in->getAddrVal(); - addr.isa = m_curr_packet_in->getAddrIS(); + addr.isa = m_last_IS = m_curr_packet_in->getAddrIS(); + if (m_P0_stack.createAddrElem(m_curr_packet_in->getType(), m_index_curr_pkt, addr) == 0) bAllocErr = true; is_addr = true; @@ -311,7 +340,8 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::decodePacket(bool &Complete) case ETM4_PKT_I_ADDR_CTXT_L_32IS0: case ETM4_PKT_I_ADDR_CTXT_L_32IS1: { - if (m_P0_stack.createContextElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getContext()) == 0) + m_last_IS = m_curr_packet_in->getAddrIS(); + if (m_P0_stack.createContextElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getContext(), m_last_IS) == 0) bAllocErr = true; } case ETM4_PKT_I_ADDR_L_32IS0: @@ -324,7 +354,8 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::decodePacket(bool &Complete) etmv4_addr_val_t addr; addr.val = m_curr_packet_in->getAddrVal(); - addr.isa = m_curr_packet_in->getAddrIS(); + addr.isa = m_last_IS = m_curr_packet_in->getAddrIS(); + if (m_P0_stack.createAddrElem(m_curr_packet_in->getType(), m_index_curr_pkt, addr) == 0) bAllocErr = true; is_addr = true; @@ -339,10 +370,7 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::decodePacket(bool &Complete) m_curr_packet_in->exception_info.exceptionType) == 0) bAllocErr = true; else - { - m_except_pending_addr = true; // wait for following packets before marking for commit. - is_except = true; - } + m_elem_pending_addr = true; // wait for following packets before marking for commit. } break; @@ -411,15 +439,67 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::decodePacket(bool &Complete) break; case ETM4_PKT_I_BAD_SEQUENCE: - resp = handleBadPacket("Bad byte sequence in packet."); + err = handleBadPacket("Bad byte sequence in packet."); break; case ETM4_PKT_I_BAD_TRACEMODE: - resp = handleBadPacket("Invalid packet type for trace mode."); + err = handleBadPacket("Invalid packet type for trace mode."); break; case ETM4_PKT_I_RESERVED: - resp = handleBadPacket("Reserved packet header"); + err = handleBadPacket("Reserved packet header"); + break; + + // speculation + case ETM4_PKT_I_MISPREDICT: + case ETM4_PKT_I_CANCEL_F1_MISPRED: + case ETM4_PKT_I_CANCEL_F2: + case ETM4_PKT_I_CANCEL_F3: + m_elem_res.mispredict = true; + if (m_curr_packet_in->getNumAtoms()) + { + if (m_P0_stack.createAtomElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getAtom()) == 0) + bAllocErr = true; + else + m_curr_spec_depth += m_curr_packet_in->getNumAtoms(); + } + + case ETM4_PKT_I_CANCEL_F1: + m_elem_res.P0_cancel = m_curr_packet_in->getCancelElem(); + break; + + case ETM4_PKT_I_COMMIT: + m_elem_res.P0_commit = m_curr_packet_in->getCommitElem(); + break; + + case ETM4_PKT_I_OVERFLOW: + m_prev_overflow = true; + case ETM4_PKT_I_DISCARD: + m_curr_spec_depth = 0; + m_elem_res.discard = true; + break; + + /* Q packets */ + case ETM4_PKT_I_Q: + { + TrcStackQElem *pQElem = m_P0_stack.createQElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->Q_pkt.q_count); + if (pQElem) + { + if (m_curr_packet_in->Q_pkt.addr_present) + { + etmv4_addr_val_t addr; + + addr.val = m_curr_packet_in->getAddrVal(); + addr.isa = m_curr_packet_in->getAddrIS(); + pQElem->setAddr(addr); + m_curr_spec_depth++; + } + else + m_elem_pending_addr = true; + } + else + bAllocErr = true; + } break; /*** presently unsupported packets ***/ @@ -432,90 +512,134 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::decodePacket(bool &Complete) case ETM4_PKT_I_COND_RES_F2: case ETM4_PKT_I_COND_RES_F3: case ETM4_PKT_I_COND_RES_F4: - // speculation - case ETM4_PKT_I_CANCEL_F1: - case ETM4_PKT_I_CANCEL_F2: - case ETM4_PKT_I_CANCEL_F3: - case ETM4_PKT_I_COMMIT: - case ETM4_PKT_I_MISPREDICT: - case ETM4_PKT_I_DISCARD: // data synchronisation markers case ETM4_PKT_I_NUM_DS_MKR: case ETM4_PKT_I_UNNUM_DS_MKR: - /* Q packets */ - case ETM4_PKT_I_Q: - resp = OCSD_RESP_FATAL_INVALID_DATA; - LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_DECODE_PKT,"Unsupported packet type.")); + // all currently unsupported + { + ocsd_err_severity_t sev = OCSD_ERR_SEV_ERROR; +#ifdef OCSD_WARN_UNSUPPORTED + sev = OCSD_ERR_SEV_WARN; + //resp = OCSD_RESP_WARN_CONT; +#else + //resp = OCSD_RESP_FATAL_INVALID_DATA; +#endif + err = OCSD_ERR_UNSUPP_DECODE_PKT; + LogError(ocsdError(sev, err, "Data trace releated, unsupported packet type.")); + } break; default: // any other packet - bad packet error - resp = OCSD_RESP_FATAL_INVALID_DATA; - LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_DECODE_PKT,"Unknown packet type.")); + err = OCSD_ERR_BAD_DECODE_PKT; + LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,"Unknown packet type.")); break; - } - // we need to wait for following address after exception + // we need to wait for following address after certain packets // - work out if we have seen enough here... - if(m_except_pending_addr && !is_except) + if (is_addr && m_elem_pending_addr) { - m_except_pending_addr = false; //next packet has to be an address - // exception packet sequence complete - if(is_addr) - { - m_curr_spec_depth++; // exceptions are P0 elements so up the spec depth to commit if needed. - } - else - { - resp = OCSD_RESP_FATAL_INVALID_DATA; - LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_DECODE_PKT,"Expected Address packet to follow exception packet.")); - } + m_curr_spec_depth++; // increase spec depth for element waiting on address. + m_elem_pending_addr = false; // can't be waiting on both } if(bAllocErr) { - resp = OCSD_RESP_FATAL_SYS_ERR; + err = OCSD_ERR_MEM; LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_MEM,"Memory allocation error.")); } else if(m_curr_spec_depth > m_max_spec_depth) { // auto commit anything above max spec depth // (this will auto commit anything if spec depth not supported!) - m_P0_commit = m_curr_spec_depth - m_max_spec_depth; - m_curr_state = COMMIT_ELEM; - Complete = false; // force the processing of the commit elements. + m_elem_res.P0_commit = m_curr_spec_depth - m_max_spec_depth; } - return resp; + + if (!err && isElemForRes()) + m_curr_state = RESOLVE_ELEM; + return err; } void TrcPktDecodeEtmV4I::doTraceInfoPacket() { m_trace_info = m_curr_packet_in->getTraceInfo(); m_cc_threshold = m_curr_packet_in->getCCThreshold(); - m_p0_key = m_curr_packet_in->getP0Key(); m_curr_spec_depth = m_curr_packet_in->getCurrSpecDepth(); + + // elements associated with data trace +#ifdef DATA_TRACE_SUPPORTED + m_p0_key = m_curr_packet_in->getP0Key(); +#endif +} + +/* Element resolution + * Commit or cancel elements as required + * Send any buffered output packets. + */ +ocsd_datapath_resp_t TrcPktDecodeEtmV4I::resolveElements() +{ + ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + bool Complete = false; + + while (!Complete) + { + if (m_out_elem.numElemToSend()) + resp = m_out_elem.sendElements(); + else if (isElemForRes()) + { + ocsd_err_t err = OCSD_OK; + if (m_elem_res.P0_commit) + err = commitElements(); + + 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; + } + + // break out on error or wait request. + if (!OCSD_DATA_RESP_IS_CONT(resp)) + break; + + // completion is nothing to send and nothing to commit + Complete = !m_out_elem.numElemToSend() && !isElemForRes(); + + // done all elements - need more packets. + if (Complete) { + // if we are still in resolve, the goto decode. + if (m_curr_state == RESOLVE_ELEM) + m_curr_state = DECODE_PKTS; + } + } + return resp; } /* * Walks through the element stack, processing from oldest element to the newest, according to the number of P0 elements that need committing. + Build a stack of output elements in the process. */ -ocsd_datapath_resp_t TrcPktDecodeEtmV4I::commitElements(bool &Complete) +ocsd_err_t TrcPktDecodeEtmV4I::commitElements() { - ocsd_datapath_resp_t resp = OCSD_RESP_CONT; - bool bPause = false; // pause commit operation + ocsd_err_t err = OCSD_OK; bool bPopElem = true; // do we remove the element from the stack (multi atom elements may need to stay!) - int num_commit_req = m_P0_commit; + int num_commit_req = m_elem_res.P0_commit; ocsd_trc_index_t err_idx = 0; - - Complete = true; // assume we exit due to completion of commit operation - TrcStackElem *pElem = 0; // stacked element pointer - while(m_P0_commit && !bPause) + err = m_out_elem.resetElemStack(); + + while(m_elem_res.P0_commit && !err) { - if(m_P0_stack.size() > 0) + if (m_P0_stack.size() > 0) { pElem = m_P0_stack.back(); // get oldest element err_idx = pElem->getRootIndex(); // save index in case of error. @@ -524,11 +648,13 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::commitElements(bool &Complete) { // indicates a trace restart - beginning of trace or discontinuiuty case P0_TRC_ON: - m_output_elem.setType(OCSD_GEN_TRC_ELEM_TRACE_ON); - m_output_elem.trace_on_reason = m_prev_overflow ? TRACE_ON_OVERFLOW : TRACE_ON_NORMAL; - m_prev_overflow = false; - resp = outputTraceElementIdx(pElem->getRootIndex(),m_output_elem); - m_return_stack.flush(); + err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_TRACE_ON); + if (!err) + { + m_out_elem.getCurrElem().trace_on_reason = m_prev_overflow ? TRACE_ON_OVERFLOW : TRACE_ON_NORMAL; + m_prev_overflow = false; + m_return_stack.flush(); + } break; case P0_ADDR: @@ -551,50 +677,20 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::commitElements(bool &Complete) etmv4_context_t ctxt = pCtxtElem->getContext(); // check this is an updated context if(ctxt.updated) - { - updateContext(pCtxtElem); - - m_output_elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); - resp = outputTraceElementIdx(pElem->getRootIndex(),m_output_elem); + { + err = m_out_elem.addElem(pElem->getRootIndex()); + if (!err) + updateContext(pCtxtElem, outElem()); } } } break; case P0_EVENT: - { - TrcStackElemParam *pParamElem = dynamic_cast(pElem); - if(pParamElem) - resp = this->outputEvent(pParamElem); - } - break; - case P0_TS: - { - TrcStackElemParam *pParamElem = dynamic_cast(pElem); - if(pParamElem) - resp = outputTS(pParamElem,false); - } - break; - case P0_CC: - { - TrcStackElemParam *pParamElem = dynamic_cast(pElem); - if(pParamElem) - resp = outputCC(pParamElem); - } - break; - case P0_TS_CC: - { - TrcStackElemParam *pParamElem = dynamic_cast(pElem); - if(pParamElem) - resp = outputTS(pParamElem,true); - } - break; - - case P0_OVERFLOW: - m_prev_overflow = true; + err = processTS_CC_EventElem(pElem); break; case P0_ATOM: @@ -603,22 +699,21 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::commitElements(bool &Complete) if(pAtomElem) { - bool bContProcess = true; - while(!pAtomElem->isEmpty() && m_P0_commit && bContProcess) + while(!pAtomElem->isEmpty() && m_elem_res.P0_commit && !err) { ocsd_atm_val atom = pAtomElem->commitOldest(); // check if prev atom left us an indirect address target on the return stack - if ((resp = returnStackPop()) != OCSD_RESP_CONT) + if ((err = returnStackPop()) != OCSD_OK) break; // if address and context do instruction trace follower. // otherwise skip atom and reduce committed elements if(!m_need_ctxt && !m_need_addr) { - resp = processAtom(atom,bContProcess); + err = processAtom(atom); } - m_P0_commit--; // mark committed + m_elem_res.P0_commit--; // mark committed } if(!pAtomElem->isEmpty()) bPopElem = false; // don't remove if still atoms to process. @@ -628,68 +723,63 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::commitElements(bool &Complete) case P0_EXCEP: // check if prev atom left us an indirect address target on the return stack - if ((resp = returnStackPop()) != OCSD_RESP_CONT) + if ((err = returnStackPop()) != OCSD_OK) break; - m_excep_info.proc = EXCEP_POP; // set state in case we need to stop part way through - resp = processException(); // output trace + exception elements. - m_P0_commit--; + err = processException(); // output trace + exception elements. + m_elem_res.P0_commit--; break; case P0_EXCEP_RET: - m_output_elem.setType(OCSD_GEN_TRC_ELEM_EXCEPTION_RET); - resp = outputTraceElementIdx(pElem->getRootIndex(),m_output_elem); - if(pElem->isP0()) // are we on a core that counts ERET as P0? - m_P0_commit--; + err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_EXCEPTION_RET); + if (!err) + { + if (pElem->isP0()) // are we on a core that counts ERET as P0? + m_elem_res.P0_commit--; + } break; case P0_FUNC_RET: // func ret is V8M - data trace only - hint that data has been popped off the stack. // at this point nothing to do till the decoder starts handling data trace. if (pElem->isP0()) - m_P0_commit--; + m_elem_res.P0_commit--; + break; + + case P0_Q: + err = processQElement(); + m_elem_res.P0_commit--; break; } if(bPopElem) m_P0_stack.delete_back(); // remove element from stack; - - // if response not continue, then break out of the loop. - if(!OCSD_DATA_RESP_IS_CONT(resp)) - { - bPause = true; - } } else { // too few elements for commit operation - decode error. - resp = OCSD_RESP_FATAL_INVALID_DATA; + 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")); - bPause = true; } } - // done all elements - need more packets. - if(m_P0_commit == 0) - m_curr_state = DECODE_PKTS; - // reduce the spec depth by number of comitted elements - m_curr_spec_depth -= (num_commit_req-m_P0_commit); - return resp; + m_curr_spec_depth -= (num_commit_req-m_elem_res.P0_commit); + return err; } -ocsd_datapath_resp_t TrcPktDecodeEtmV4I::returnStackPop() +ocsd_err_t TrcPktDecodeEtmV4I::returnStackPop() { - ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + ocsd_err_t err = OCSD_OK; ocsd_isa nextISA; - + if (m_return_stack.pop_pending()) { ocsd_vaddr_t popAddr = m_return_stack.pop(nextISA); if (m_return_stack.overflow()) { - resp = OCSD_RESP_FATAL_INVALID_DATA; - LogError(ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_RET_STACK_OVERFLOW, "Trace Return Stack Overflow.")); + err = OCSD_ERR_RET_STACK_OVERFLOW; + LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, "Trace Return Stack Overflow.")); } else { @@ -698,20 +788,23 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::returnStackPop() m_need_addr = false; } } - return resp; + return err; } -ocsd_datapath_resp_t TrcPktDecodeEtmV4I::flushEOT() +ocsd_err_t TrcPktDecodeEtmV4I::commitElemOnEOT() { - ocsd_datapath_resp_t resp = OCSD_RESP_CONT; - if(m_flush_EOT) + ocsd_err_t err = OCSD_OK; + TrcStackElem *pElem = 0; + + // nothing outstanding - reset the stack before we add more + if (!m_out_elem.numElemToSend()) + m_out_elem.resetElemStack(); + + while((m_P0_stack.size() > 0) && !err) { - TrcStackElem *pElem = 0; - while(OCSD_DATA_RESP_IS_CONT(resp) && (m_P0_stack.size() > 0)) - { - // scan for outstanding events, TS and CC, before any outstanding - // P0 commit elements. - pElem = m_P0_stack.back(); + // scan for outstanding events, TS and CC, that appear before any outstanding + // uncommited P0 element. + pElem = m_P0_stack.back(); switch(pElem->getP0Type()) { @@ -722,104 +815,293 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::flushEOT() case P0_EXCEP: case P0_EXCEP_RET: case P0_OVERFLOW: + case P0_Q: m_P0_stack.delete_all(); break; - //skip - case P0_ADDR: - case P0_CTXT: - break; + //skip + case P0_ADDR: + case P0_CTXT: + break; - // output - case P0_EVENT: - { - TrcStackElemParam *pParamElem = dynamic_cast(pElem); - if(pParamElem) - resp = this->outputEvent(pParamElem); - } - break; - - case P0_TS: - { - TrcStackElemParam *pParamElem = dynamic_cast(pElem); - if(pParamElem) - resp = outputTS(pParamElem,false); - } - break; - - case P0_CC: - { - TrcStackElemParam *pParamElem = dynamic_cast(pElem); - if(pParamElem) - resp = outputCC(pParamElem); - } - break; - - case P0_TS_CC: - { - TrcStackElemParam *pParamElem = dynamic_cast(pElem); - if(pParamElem) - resp = outputTS(pParamElem,true); - } - break; - } - m_P0_stack.delete_back(); + // output + case P0_EVENT: + case P0_TS: + case P0_CC: + case P0_TS_CC: + err = processTS_CC_EventElem(pElem); + break; } + m_P0_stack.delete_back(); + } - if(OCSD_DATA_RESP_IS_CONT(resp) && (m_P0_stack.size() == 0)) + if(!err) + { + err = m_out_elem.addElemType(m_index_curr_pkt, OCSD_GEN_TRC_ELEM_EO_TRACE); + outElem().setUnSyncEOTReason(m_prev_overflow ? UNSYNC_OVERFLOW : UNSYNC_EOT); + } + return err; +} + +// cancel elements. These not output +ocsd_err_t TrcPktDecodeEtmV4I::cancelElements() +{ + ocsd_err_t err = OCSD_OK; + bool P0StackDone = false; // checked all P0 elements on the stack + TrcStackElem *pElem = 0; // stacked element pointer + EtmV4P0Stack temp; + int num_cancel_req = m_elem_res.P0_cancel; + + while (m_elem_res.P0_cancel) + { + //search the stack for the newest elements + if (!P0StackDone) { - m_output_elem.setType(OCSD_GEN_TRC_ELEM_EO_TRACE); - resp = outputTraceElement(m_output_elem); - m_flush_EOT = false; + if (m_P0_stack.size() == 0) + P0StackDone = true; + else + { + // get the newest element + pElem = m_P0_stack.front(); + if (pElem->isP0()) { + if (pElem->getP0Type() == P0_ATOM) + { + TrcStackElemAtom *pAtomElem = (TrcStackElemAtom *)pElem; + // atom - cancel N atoms + m_elem_res.P0_cancel -= pAtomElem->cancelNewest(m_elem_res.P0_cancel); + if (pAtomElem->isEmpty()) + m_P0_stack.delete_front(); // remove the element + } + else + { + m_elem_res.P0_cancel--; + m_P0_stack.delete_front(); // remove the element + } + } else { + // not P0, make a keep / remove decision + switch (pElem->getP0Type()) + { + // keep these + case P0_EVENT: + case P0_TS: + case P0_CC: + case P0_TS_CC: + m_P0_stack.pop_front(false); + temp.push_back(pElem); + break; + + default: + m_P0_stack.delete_front(); + break; + } + } + } + } + // may have some unseen elements + else if (m_unseen_spec_elem) + { + m_unseen_spec_elem--; + m_elem_res.P0_cancel--; + } + // otherwise we have some sort of overrun + else + { + // 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")); + m_elem_res.P0_cancel = 0; + break; + } + + if (temp.size()) + { + while (temp.size()) + { + pElem = temp.back(); + m_P0_stack.push_front(pElem); + temp.pop_back(false); + } } } - return resp; + m_curr_spec_depth -= num_cancel_req - m_elem_res.P0_cancel; + return err; } -ocsd_datapath_resp_t TrcPktDecodeEtmV4I::outputCC(TrcStackElemParam *pParamElem) +// mispredict an atom +ocsd_err_t TrcPktDecodeEtmV4I::mispredictAtom() { - m_output_elem.setType(OCSD_GEN_TRC_ELEM_CYCLE_COUNT); - m_output_elem.setCycleCount(pParamElem->getParam(0)); - return outputTraceElementIdx(pParamElem->getRootIndex(),m_output_elem); + ocsd_err_t err = OCSD_OK; + bool bFoundAtom = false, bDone = false; + TrcStackElem *pElem = 0; + + m_P0_stack.from_front_init(); // init iterator at front. + while (!bDone) + { + pElem = m_P0_stack.from_front_next(); + if (pElem) + { + if (pElem->getP0Type() == P0_ATOM) + { + TrcStackElemAtom *pAtomElem = dynamic_cast(pElem); + if (pAtomElem) + { + pAtomElem->mispredictNewest(); + bFoundAtom = true; + } + bDone = true; + } + else if (pElem->getP0Type() == P0_ADDR) + { + // need to disregard any addresses that appear between mispredict and the atom in question + m_P0_stack.erase_curr_from_front(); + } + } + else + bDone = true; + } + + // if missed atom then either overrun error or mispredict on unseen element + 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")); + } + m_elem_res.mispredict = false; + return err; } -ocsd_datapath_resp_t TrcPktDecodeEtmV4I::outputTS(TrcStackElemParam *pParamElem, bool withCC) +// discard elements and flush +ocsd_err_t TrcPktDecodeEtmV4I::discardElements() { - m_output_elem.setType(OCSD_GEN_TRC_ELEM_TIMESTAMP); - m_output_elem.timestamp = (uint64_t)(pParamElem->getParam(0)) | (((uint64_t)pParamElem->getParam(1)) << 32); - if(withCC) - m_output_elem.setCycleCount(pParamElem->getParam(2)); - return outputTraceElementIdx(pParamElem->getRootIndex(),m_output_elem); + ocsd_err_t err = OCSD_OK; + TrcStackElem *pElem = 0; // stacked element pointer + + // dump P0, elemnts - output remaining CC / TS + while ((m_P0_stack.size() > 0) && !err) + { + pElem = m_P0_stack.back(); + err = processTS_CC_EventElem(pElem); + m_P0_stack.delete_back(); + } + + // clear all speculation info + clearElemRes(); + m_curr_spec_depth = 0; + + // set decode state + m_curr_state = NO_SYNC; + m_unsync_eot_info = m_prev_overflow ? UNSYNC_OVERFLOW : UNSYNC_DISCARD; + + // unsync so need context & address. + m_need_ctxt = true; + m_need_addr = true; + m_elem_pending_addr = false; + return err; } -ocsd_datapath_resp_t TrcPktDecodeEtmV4I::outputEvent(TrcStackElemParam *pParamElem) +ocsd_err_t TrcPktDecodeEtmV4I::processTS_CC_EventElem(TrcStackElem *pElem) { - m_output_elem.setType(OCSD_GEN_TRC_ELEM_EVENT); - m_output_elem.trace_event.ev_type = EVENT_NUMBERED; - m_output_elem.trace_event.ev_number = pParamElem->getParam(0); - return outputTraceElementIdx(pParamElem->getRootIndex(),m_output_elem); + ocsd_err_t err = OCSD_OK; + + switch (pElem->getP0Type()) + { + case P0_EVENT: + { + TrcStackElemParam *pParamElem = dynamic_cast(pElem); + if (pParamElem) + err = addElemEvent(pParamElem); + } + break; + + case P0_TS: + { + TrcStackElemParam *pParamElem = dynamic_cast(pElem); + if (pParamElem) + err = addElemTS(pParamElem, false); + } + break; + + case P0_CC: + { + TrcStackElemParam *pParamElem = dynamic_cast(pElem); + if (pParamElem) + err = addElemCC(pParamElem); + } + break; + + case P0_TS_CC: + { + TrcStackElemParam *pParamElem = dynamic_cast(pElem); + if (pParamElem) + err = addElemTS(pParamElem, true); + } + break; + } + return err; + } -ocsd_datapath_resp_t TrcPktDecodeEtmV4I::outputTraceRange(const bool executed, ocsd_trc_index_t index) +ocsd_err_t TrcPktDecodeEtmV4I::addElemCC(TrcStackElemParam *pParamElem) { - m_output_elem.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE); - m_output_elem.setLastInstrInfo(executed, m_instr_info.type, m_instr_info.sub_type, m_instr_info.instr_size); - m_output_elem.setISA(m_instr_info.isa); - m_output_elem.setLastInstrCond(m_instr_info.is_conditional); + ocsd_err_t err = OCSD_OK; + + err = m_out_elem.addElemType(pParamElem->getRootIndex(), OCSD_GEN_TRC_ELEM_CYCLE_COUNT); + if (!err) + outElem().setCycleCount(pParamElem->getParam(0)); + return err; +} + +ocsd_err_t TrcPktDecodeEtmV4I::addElemTS(TrcStackElemParam *pParamElem, bool withCC) +{ + ocsd_err_t err = OCSD_OK; + + err = m_out_elem.addElemType(pParamElem->getRootIndex(), OCSD_GEN_TRC_ELEM_TIMESTAMP); + if (!err) + { + outElem().timestamp = (uint64_t)(pParamElem->getParam(0)) | (((uint64_t)pParamElem->getParam(1)) << 32); + if (withCC) + outElem().setCycleCount(pParamElem->getParam(2)); + } + return err; +} + +ocsd_err_t TrcPktDecodeEtmV4I::addElemEvent(TrcStackElemParam *pParamElem) +{ + ocsd_err_t err = OCSD_OK; + + err = m_out_elem.addElemType(pParamElem->getRootIndex(), OCSD_GEN_TRC_ELEM_EVENT); + if (!err) + { + outElem().trace_event.ev_type = EVENT_NUMBERED; + outElem().trace_event.ev_number = pParamElem->getParam(0); + } + return err; +} + +void TrcPktDecodeEtmV4I::setElemTraceRange(OcsdTraceElement &elemIn, const instr_range_t &addr_range, + const bool executed, ocsd_trc_index_t index) +{ + 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.setAddrRange(addr_range.st_addr, addr_range.en_addr, addr_range.num_instr); if (executed) m_instr_info.isa = m_instr_info.next_isa; - return outputTraceElementIdx(index, m_output_elem); } -ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom, bool &bCont) +ocsd_err_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom) { - ocsd_datapath_resp_t resp = OCSD_RESP_CONT; - TrcStackElem *pElem = m_P0_stack.back(); // get the atom element - bool bWPFound = false; ocsd_err_t err; - bCont = true; + TrcStackElem *pElem = m_P0_stack.back(); // get the atom element + WP_res_t WPRes; + instr_range_t addr_range; - err = traceInstrToWP(bWPFound); + // new element for this processed atom + if ((err = m_out_elem.addElem(pElem->getRootIndex())) != OCSD_OK) + return err; + + err = traceInstrToWP(addr_range, WPRes); if(err != OCSD_OK) { if(err == OCSD_ERR_UNSUPPORTED_ISA) @@ -828,18 +1110,16 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom, bo m_need_ctxt = true; LogError(ocsdError(OCSD_ERR_SEV_WARN,err,pElem->getRootIndex(),m_CSID,"Warning: unsupported instruction set processing atom packet.")); // wait for next context - return resp; + return OCSD_OK; } else { - bCont = false; - resp = OCSD_RESP_FATAL_INVALID_DATA; LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,pElem->getRootIndex(),m_CSID,"Error processing atom packet.")); - return resp; + return err; } } - if(bWPFound) + if(WPFound(WPRes)) { // save recorded next instuction address ocsd_vaddr_t nextAddr = m_instr_info.instr_addr; @@ -867,125 +1147,113 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom, bo } break; } - resp = outputTraceRange((atom == ATOM_E), pElem->getRootIndex()); - + setElemTraceRange(outElem(), addr_range, (atom == ATOM_E), pElem->getRootIndex()); } else { // no waypoint - likely inaccessible memory range. m_need_addr = true; // need an address update - if(m_output_elem.st_addr != m_output_elem.en_addr) + if(addr_range.st_addr != addr_range.en_addr) { // some trace before we were out of memory access range - resp = outputTraceRange(true, pElem->getRootIndex()); + setElemTraceRange(outElem(), addr_range, true, pElem->getRootIndex()); + + // another element for the nacc... + if (WPNacc(WPRes)) + err = m_out_elem.addElem(pElem->getRootIndex()); } - if(m_mem_nacc_pending && OCSD_DATA_RESP_IS_CONT(resp)) + if(WPNacc(WPRes) && !err) { - m_output_elem.setType(OCSD_GEN_TRC_ELEM_ADDR_NACC); - m_output_elem.st_addr = m_nacc_addr; - resp = outputTraceElementIdx(pElem->getRootIndex(),m_output_elem); - m_mem_nacc_pending = false; + outElem().setType(OCSD_GEN_TRC_ELEM_ADDR_NACC); + outElem().st_addr = m_instr_info.instr_addr; } } - - if(!OCSD_DATA_RESP_IS_CONT(resp)) - bCont = false; - - return resp; + return err; } // Exception processor -ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processException() +ocsd_err_t TrcPktDecodeEtmV4I::processException() { - ocsd_datapath_resp_t resp = OCSD_RESP_CONT; - TrcStackElemExcept *pExceptElem; + ocsd_err_t err; + TrcStackElem *pElem = 0; + TrcStackElemExcept *pExceptElem = 0; + TrcStackElemAddr *pAddressElem = 0; + TrcStackElemCtxt *pCtxtElem = 0; + bool branch_target = false; // exception address implies prior branch target address + ocsd_vaddr_t excep_ret_addr; + ocsd_trc_index_t excep_pkt_index; + WP_res_t WPRes = WP_NOT_FOUND; - m_excep_info.addr_b_tgt = false; - - if(m_excep_info.proc == EXCEP_POP) + // 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(); + m_P0_stack.pop_back(); // remove the exception element + + pElem = m_P0_stack.back(); // look at next element. + if(pElem->getP0Type() == P0_CTXT) { - pExceptElem = dynamic_cast(m_P0_stack.back()); // get the exception element - TrcStackElemAddr *pAddressElem = 0; - TrcStackElemCtxt *pCtxtElem = 0; - TrcStackElem *pElem = 0; - - m_P0_stack.pop_back(); // remove the exception element - pElem = m_P0_stack.back(); // look at next element. - if(pElem->getP0Type() == P0_CTXT) - { - 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 - } + 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) + 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) { - // no following address element - indicate processing error. - resp = OCSD_RESP_FATAL_INVALID_DATA; - LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,pExceptElem->getRootIndex(),m_CSID,"Address missing in exception packet.")); - } - else - { - // extract address - pAddressElem = static_cast(pElem); - - // fill in exception info for use later - m_excep_info.addr = pAddressElem->getAddr(); - m_excep_info.number = pExceptElem->getExcepNum(); - m_excep_info.index = pExceptElem->getRootIndex(); - m_excep_info.addr_b_tgt = pExceptElem->getPrevSame(); - - // see if there is an address + optional context element implied - // prior to the exception. - if (m_excep_info.addr_b_tgt) - { - // this was a branch target address - update current setting - bool b64bit = m_instr_info.isa == ocsd_isa_aarch64; - if (pCtxtElem) { - b64bit = pCtxtElem->getContext().SF; - } - m_instr_info.instr_addr = m_excep_info.addr.val; - m_instr_info.isa = (m_excep_info.addr.isa == 0) ? - (b64bit ? ocsd_isa_aarch64 : ocsd_isa_arm) : ocsd_isa_thumb2; - m_need_addr = false; - } - - // figure out next move + // this was a branch target address - update current setting + bool b64bit = m_instr_info.isa == ocsd_isa_aarch64; if (pCtxtElem) { - m_excep_info.proc = EXCEP_CTXT; - updateContext(pCtxtElem); + b64bit = pCtxtElem->getContext().SF; } - else if(m_excep_info.addr.val == m_instr_info.instr_addr) - m_excep_info.proc = EXCEP_EXCEP; - else - m_excep_info.proc = EXCEP_RANGE; + + // 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; } - m_P0_stack.delete_popped(); + } + + // need to output something - set up an element + if ((err = m_out_elem.addElem(excep_pkt_index))) + return err; + + // output a context element if present + if (pCtxtElem) + { + updateContext(pCtxtElem, outElem()); + + // used the element - need another for later stages + if ((err = m_out_elem.addElem(excep_pkt_index))) + return err; } - // output a context element - if (m_excep_info.proc == EXCEP_CTXT) - { - m_output_elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); - resp = outputTraceElementIdx(m_excep_info.index, m_output_elem); - m_excep_info.proc = EXCEP_EXCEP; - if (!OCSD_DATA_RESP_IS_CONT(resp)) - return resp; - } - - // output a range element - if(m_excep_info.proc == EXCEP_RANGE) - { - bool bWPFound = false; - ocsd_err_t err; - - // last instr_info address is the start address - m_output_elem.st_addr = m_instr_info.instr_addr; + // 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(bWPFound,true,m_excep_info.addr.val); + err = traceInstrToWP(addr_range, WPRes, true, excep_ret_addr); if(err != OCSD_OK) { @@ -993,90 +1261,221 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processException() { m_need_addr = true; m_need_ctxt = true; - LogError(ocsdError(OCSD_ERR_SEV_WARN,err,m_excep_info.index,m_CSID,"Warning: unsupported instruction set processing exception packet.")); + LogError(ocsdError(OCSD_ERR_SEV_WARN,err, excep_pkt_index,m_CSID,"Warning: unsupported instruction set processing exception packet.")); } else { - resp = OCSD_RESP_FATAL_INVALID_DATA; - LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,m_excep_info.index,m_CSID,"Error processing exception packet.")); - m_excep_info.proc = EXCEP_POP; // nothing more to do, reset to start of exception handling + LogError(ocsdError(OCSD_ERR_SEV_ERROR,err, excep_pkt_index,m_CSID,"Error processing exception packet.")); } + return err; } - if(bWPFound) + if(WPFound(WPRes)) { // waypoint address found - output range - resp = outputTraceRange(true, m_excep_info.index); - m_excep_info.proc = EXCEP_EXCEP; + 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(m_output_elem.st_addr != m_output_elem.en_addr) + if(addr_range.st_addr != addr_range.en_addr) { // some trace before we were out of memory access range - resp = outputTraceRange(true, m_excep_info.index); + setElemTraceRange(outElem(), addr_range, true, excep_pkt_index); + range_out = true; } - - m_excep_info.proc = m_mem_nacc_pending ? EXCEP_NACC : EXCEP_EXCEP; } - } - - if((m_excep_info.proc == EXCEP_NACC) && OCSD_DATA_RESP_IS_CONT(resp)) + + // used the element need another for NACC or EXCEP. + if (range_out) + { + if ((err = m_out_elem.addElem(excep_pkt_index))) + return err; + } + } + + // watchpoint walk resulted in inaccessible memory call... + if (WPNacc(WPRes)) { - m_output_elem.setType(OCSD_GEN_TRC_ELEM_ADDR_NACC); - m_output_elem.st_addr = m_nacc_addr; - resp = outputTraceElementIdx(m_excep_info.index,m_output_elem); - m_excep_info.proc = EXCEP_EXCEP; - m_mem_nacc_pending = false; + + 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; } - if((m_excep_info.proc == EXCEP_EXCEP) && OCSD_DATA_RESP_IS_CONT(resp)) + // output exception element. + outElem().setType(OCSD_GEN_TRC_ELEM_EXCEPTION); + + // add end address as preferred return address to end addr in element + outElem().en_addr = excep_ret_addr; + outElem().excep_ret_addr = 1; + outElem().excep_ret_addr_br_tgt = branch_target; + outElem().exception_number = pExceptElem->getExcepNum(); + + m_P0_stack.delete_popped(); // clear the used elements from the stack + return err; +} + +ocsd_err_t TrcPktDecodeEtmV4I::processQElement() +{ + ocsd_err_t err = OCSD_OK; + TrcStackQElem *pQElem; + etmv4_addr_val_t QAddr; // address where trace restarts + int iCount = 0; + + pQElem = dynamic_cast(m_P0_stack.back()); // get the exception element + m_P0_stack.pop_back(); // remove the Q element. + + if (!pQElem->hasAddr()) // no address - it must be next on the stack.... { - // output element. - m_output_elem.setType(OCSD_GEN_TRC_ELEM_EXCEPTION); - // add end address as preferred return address to end addr in element - m_output_elem.en_addr = m_excep_info.addr.val; - m_output_elem.excep_ret_addr = 1; - m_output_elem.excep_ret_addr_br_tgt = m_excep_info.addr_b_tgt; - m_output_elem.exception_number = m_excep_info.number; - resp = outputTraceElementIdx(m_excep_info.index,m_output_elem); - m_excep_info.proc = EXCEP_POP; - } - return resp; + TrcStackElemAddr *pAddressElem = 0; + TrcStackElemCtxt *pCtxtElem = 0; + TrcStackElem *pElem = 0; + + pElem = m_P0_stack.back(); // look at next element. + if (pElem->getP0Type() == P0_CTXT) + { + 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 = OCSD_ERR_BAD_PACKET_SEQ; + LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pQElem->getRootIndex(), m_CSID, "Address missing in Q packet.")); + m_P0_stack.delete_popped(); + return err; + } + pAddressElem = dynamic_cast(pElem); + QAddr = pAddressElem->getAddr(); + m_P0_stack.pop_back(); // remove the address element + m_P0_stack.delete_popped(); // clear used elements + + // return the context element for processing next time. + if (pCtxtElem) + { + // need a new copy at the back - old one will be deleted as popped. + m_P0_stack.createContextElem(pCtxtElem->getRootPkt(), pCtxtElem->getRootIndex(), pCtxtElem->getContext(),true); + } + } + else + QAddr = pQElem->getAddr(); + + // process the Q element with address. + iCount = pQElem->getInstrCount(); + + bool isBranch = false; + + // need to output something - set up an element + if ((err = m_out_elem.addElem(pQElem->getRootIndex()))) + return err; + + instr_range_t addr_range; + addr_range.st_addr = addr_range.en_addr = m_instr_info.instr_addr; + addr_range.num_instr = 0; + + // walk iCount instructions + for (int i = 0; i < iCount; i++) + { + uint32_t opcode; + uint32_t bytesReq = 4; + + err = accessMemory(m_instr_info.instr_addr, getCurrMemSpace(), &bytesReq, (uint8_t *)&opcode); + if (err != OCSD_OK) break; + + if (bytesReq == 4) // got data back + { + m_instr_info.opcode = opcode; + err = instrDecode(&m_instr_info); + if (err != OCSD_OK) break; + + // increment address - may be adjusted by direct branch value later + m_instr_info.instr_addr += m_instr_info.instr_size; + addr_range.num_instr++; + + isBranch = (m_instr_info.type == OCSD_INSTR_BR) || + (m_instr_info.type == OCSD_INSTR_BR_INDIRECT); + + // on a branch no way of knowing if taken - bail out + if (isBranch) + break; + } + else + break; // missing memory + + } + + if (err == OCSD_OK) + { + bool inCompleteRange = true; + if (iCount && (addr_range.num_instr == (unsigned)iCount)) + { + if ((m_instr_info.instr_addr == QAddr.val) || // complete range + (isBranch)) // or ends on branch - only way we know if branch taken. + { + // output a range and continue + inCompleteRange = false; + // update the range decoded address in the output packet. + addr_range.en_addr = m_instr_info.instr_addr; + setElemTraceRange(outElem(), addr_range, true, pQElem->getRootIndex()); + } + } + + if (inCompleteRange) + { + // unknown instructions executed. + addr_range.en_addr = QAddr.val; + addr_range.num_instr = iCount; + + outElem().setType(OCSD_GEN_TRC_ELEM_I_RANGE_NOPATH); + outElem().setAddrRange(addr_range.st_addr, addr_range.en_addr, addr_range.num_instr); + outElem().setISA(calcISA(m_is_64bit, QAddr.isa)); + } + + // after the Q element, tracing resumes at the address supplied + SetInstrInfoInAddrISA(QAddr.val, QAddr.isa); + m_need_addr = false; + } + else + { + // output error and halt decode. + LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pQElem->getRootIndex(), m_CSID, "Error processing Q packet")); + } + m_P0_stack.delete_popped(); + return err; } void TrcPktDecodeEtmV4I::SetInstrInfoInAddrISA(const ocsd_vaddr_t addr_val, const uint8_t isa) { m_instr_info.instr_addr = addr_val; - if(m_is_64bit) - m_instr_info.isa = ocsd_isa_aarch64; - else - m_instr_info.isa = (isa == 0) ? ocsd_isa_arm : ocsd_isa_thumb2; + m_instr_info.isa = calcISA(m_is_64bit, isa); } // trace an instruction range to a waypoint - and set next address to restart from. -ocsd_err_t TrcPktDecodeEtmV4I::traceInstrToWP(bool &bWPFound, const bool traceToAddrNext /*= false*/, const ocsd_vaddr_t nextAddrMatch /*= 0*/) +ocsd_err_t TrcPktDecodeEtmV4I::traceInstrToWP(instr_range_t &range, WP_res_t &WPRes, const bool traceToAddrNext /*= false*/, const ocsd_vaddr_t nextAddrMatch /*= 0*/) { uint32_t opcode; uint32_t bytesReq; ocsd_err_t err = OCSD_OK; - // TBD?: update mem space to allow for EL as well. - ocsd_mem_space_acc_t mem_space = m_is_secure ? OCSD_MEM_SPACE_S : OCSD_MEM_SPACE_N; + range.st_addr = range.en_addr = m_instr_info.instr_addr; + range.num_instr = 0; - m_output_elem.st_addr = m_output_elem.en_addr = m_instr_info.instr_addr; - m_output_elem.num_instr_range = 0; + WPRes = WP_NOT_FOUND; - bWPFound = false; - - while(!bWPFound && !m_mem_nacc_pending) + while(WPRes == WP_NOT_FOUND) { // start off by reading next opcode; bytesReq = 4; - err = accessMemory(m_instr_info.instr_addr,mem_space,&bytesReq,(uint8_t *)&opcode); + err = accessMemory(m_instr_info.instr_addr, getCurrMemSpace(),&bytesReq,(uint8_t *)&opcode); if(err != OCSD_OK) break; if(bytesReq == 4) // got data back @@ -1087,69 +1486,100 @@ ocsd_err_t TrcPktDecodeEtmV4I::traceInstrToWP(bool &bWPFound, const bool traceTo // increment address - may be adjusted by direct branch value later m_instr_info.instr_addr += m_instr_info.instr_size; - - // update the range decoded address in the output packet. - m_output_elem.en_addr = m_instr_info.instr_addr; - m_output_elem.num_instr_range++; + range.num_instr++; // either walking to match the next instruction address or a real watchpoint - if(traceToAddrNext) - bWPFound = (m_output_elem.en_addr == nextAddrMatch); - else - bWPFound = (m_instr_info.type != OCSD_INSTR_OTHER); + if (traceToAddrNext) + { + if (m_instr_info.instr_addr == nextAddrMatch) + WPRes = WP_FOUND; + } + else if (m_instr_info.type != OCSD_INSTR_OTHER) + WPRes = WP_FOUND; } else { // not enough memory accessible. - m_mem_nacc_pending = true; - m_nacc_addr = m_instr_info.instr_addr; + WPRes = WP_NACC; } } + // update the range decoded address in the output packet. + range.en_addr = m_instr_info.instr_addr; + return err; +} + +void TrcPktDecodeEtmV4I::updateContext(TrcStackElemCtxt *pCtxtElem, OcsdTraceElement &elem) +{ + etmv4_context_t ctxt = pCtxtElem->getContext(); + + elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); + + // map to output element and local saved state. + 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; + elem.context.exception_level = (ocsd_ex_level)ctxt.EL; + elem.context.el_valid = 1; + if(ctxt.updated_c) + { + elem.context.ctxt_id_valid = 1; + m_context_id = elem.context.context_id = ctxt.ctxtID; + } + if(ctxt.updated_v) + { + elem.context.vmid_valid = 1; + m_vmid_id = elem.context.vmid = ctxt.VMID; + } + + // need to update ISA in case context follows address. + elem.isa = m_instr_info.isa = calcISA(m_is_64bit, pCtxtElem->getIS()); + m_need_ctxt = false; +} + +ocsd_err_t TrcPktDecodeEtmV4I::handleBadPacket(const char *reason) +{ + ocsd_err_t err = OCSD_OK; + + if(getComponentOpMode() & OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS) + { + // 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; + } return err; } -void TrcPktDecodeEtmV4I::updateContext(TrcStackElemCtxt *pCtxtElem) +inline ocsd_mem_space_acc_t TrcPktDecodeEtmV4I::getCurrMemSpace() { - etmv4_context_t ctxt = pCtxtElem->getContext(); - // map to output element and local saved state. - m_is_64bit = (ctxt.SF != 0); - m_output_elem.context.bits64 = ctxt.SF; - m_is_secure = (ctxt.NS == 0); - m_output_elem.context.security_level = ctxt.NS ? ocsd_sec_nonsecure : ocsd_sec_secure; - m_output_elem.context.exception_level = (ocsd_ex_level)ctxt.EL; - m_output_elem.context.el_valid = 1; - if(ctxt.updated_c) - { - m_output_elem.context.ctxt_id_valid = 1; - m_context_id = m_output_elem.context.context_id = ctxt.ctxtID; - } - if(ctxt.updated_v) - { - m_output_elem.context.vmid_valid = 1; - m_vmid_id = m_output_elem.context.vmid = ctxt.VMID; - } - m_need_ctxt = false; + static ocsd_mem_space_acc_t SMemSpace[] = { + OCSD_MEM_SPACE_EL1S, + OCSD_MEM_SPACE_EL1S, + OCSD_MEM_SPACE_EL2S, + OCSD_MEM_SPACE_EL3 + }; + + static ocsd_mem_space_acc_t NSMemSpace[] = { + OCSD_MEM_SPACE_EL1N, + OCSD_MEM_SPACE_EL1N, + OCSD_MEM_SPACE_EL2, + OCSD_MEM_SPACE_EL3 + }; + + /* if no valid EL value - just use S/NS */ + if (!outElem().context.el_valid) + return m_is_secure ? OCSD_MEM_SPACE_S : OCSD_MEM_SPACE_N; + + /* mem space according to EL + S/NS */ + int el = (int)(outElem().context.exception_level) & 0x3; + return m_is_secure ? SMemSpace[el] : NSMemSpace[el]; } - -ocsd_datapath_resp_t TrcPktDecodeEtmV4I::handleBadPacket(const char *reason) -{ - ocsd_datapath_resp_t resp = OCSD_RESP_CONT; - - if(getComponentOpMode() && OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS) - { - // error out - stop decoding - resp = OCSD_RESP_FATAL_INVALID_DATA; - LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_DECODE_PKT,reason)); - } - else - { - // switch to unsync - clear decode state - m_output_elem.setType(OCSD_GEN_TRC_ELEM_NO_SYNC); - resp = outputTraceElement(m_output_elem); - resetDecoder(); - m_curr_state = WAIT_SYNC; - } - return resp; -} - /* End of File trc_pkt_decode_etmv4i.cpp */ diff --git a/contrib/opencsd/decoder/source/etmv4/trc_pkt_elem_etmv4d.cpp b/contrib/opencsd/decoder/source/etmv4/trc_pkt_elem_etmv4d.cpp deleted file mode 100644 index 58343b4117bf..000000000000 --- a/contrib/opencsd/decoder/source/etmv4/trc_pkt_elem_etmv4d.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * \file trc_pkt_elem_etmv4d.cpp - * \brief OpenCSD : - * - * \copyright Copyright (c) 2015, 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/etmv4/trc_pkt_elem_etmv4d.h" - -EtmV4DTrcPacket::EtmV4DTrcPacket() -{ -} - -EtmV4DTrcPacket::~EtmV4DTrcPacket() -{ -} - - // printing -void EtmV4DTrcPacket::toString(std::string &str) const -{ -} - -void EtmV4DTrcPacket::toStringFmt(const uint32_t fmtFlags, std::string &str) const -{ -} - - - -/* End of File trc_pkt_elem_etmv4d.cpp */ 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 3f9d534db82c..853fde499a1b 100644 --- a/contrib/opencsd/decoder/source/etmv4/trc_pkt_elem_etmv4i.cpp +++ b/contrib/opencsd/decoder/source/etmv4/trc_pkt_elem_etmv4i.cpp @@ -161,6 +161,7 @@ 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 << " }"; if (trace_info.bits.cc_enabled) oss << "; CC_THRESHOLD=" << std::hex << "0x" << cc_threshold; str += oss.str(); @@ -176,8 +177,96 @@ void EtmV4ITrcPacket::toString(std::string &str) const str += oss.str(); } break; + + case ETM4_PKT_I_CANCEL_F1: + { + std::ostringstream oss; + oss << "; Cancel(" << std::dec << cancel_elements << ")"; + str += oss.str(); + } + break; + + case ETM4_PKT_I_CANCEL_F1_MISPRED: + { + std::ostringstream oss; + oss << "; Cancel(" << std::dec << cancel_elements << "), Mispredict"; + str += oss.str(); + } + break; + + case ETM4_PKT_I_MISPREDICT: + { + std::ostringstream oss; + oss << "; "; + if (atom.num) { + atomSeq(valStr); + oss << "Atom: " << valStr << ", "; + } + oss << "Mispredict"; + str += oss.str(); + } + break; + + case ETM4_PKT_I_CANCEL_F2: + { + std::ostringstream oss; + oss << "; "; + if (atom.num) { + atomSeq(valStr); + oss << "Atom: " << valStr << ", "; + } + oss << "Cancel(1), Mispredict"; + str += oss.str(); + } + break; + + case ETM4_PKT_I_CANCEL_F3: + { + std::ostringstream oss; + oss << "; "; + if (atom.num) { + oss << "Atom: E, "; + } + oss << "Cancel(" << std::dec << cancel_elements << "), Mispredict"; + str += oss.str(); + } + break; + + case ETM4_PKT_I_COMMIT: + { + std::ostringstream oss; + oss << "; Commit(" << std::dec << commit_elements << ")"; + str += oss.str(); + } + break; + + case ETM4_PKT_I_Q: + { + std::ostringstream oss; + if (Q_pkt.count_present) + { + oss << "; Count(" << std::dec << Q_pkt.q_count << ")"; + str += oss.str(); + } + else + str += "; Count(Unknown)"; + + if (Q_pkt.addr_match) + { + addrMatchIdx(valStr); + str += "; " + valStr; + } + + if (Q_pkt.addr_present || Q_pkt.addr_match) + { + 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; + } + } + break; } -} + +} void EtmV4ITrcPacket::toStringFmt(const uint32_t fmtFlags, std::string &str) const { @@ -296,6 +385,12 @@ const char *EtmV4ITrcPacket::packetTypeName(const ocsd_etmv4_i_pkt_type type, co pDesc = "Cancel Format 1."; break; + case ETM4_PKT_I_CANCEL_F1_MISPRED: + pName = "I_CANCEL_F1_MISPRED"; + pDesc = "Cancel Format 1 + Mispredict."; + break; + + case ETM4_PKT_I_MISPREDICT: pName = "I_MISPREDICT"; pDesc = "Mispredict."; diff --git a/contrib/opencsd/decoder/source/etmv4/trc_pkt_proc_etmv4.cpp b/contrib/opencsd/decoder/source/etmv4/trc_pkt_proc_etmv4.cpp deleted file mode 100644 index b8c4f819c2d3..000000000000 --- a/contrib/opencsd/decoder/source/etmv4/trc_pkt_proc_etmv4.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - * \file trc_pkt_proc_etmv4.cpp - * \brief OpenCSD : - * - * \copyright Copyright (c) 2015, 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/etmv4/trc_pkt_proc_etmv4.h" -#include "trc_pkt_proc_etmv4i_impl.h" -#include "common/ocsd_error.h" - -#ifdef __GNUC__ -// G++ doesn't like the ## pasting -#define ETMV4I_PKTS_NAME "PKTP_ETMV4I" -#else -// VC++ is fine -#define ETMV4I_PKTS_NAME OCSD_CMPNAME_PREFIX_PKTPROC##"_ETMV4I" -#endif - -static const uint32_t ETMV4_SUPPORTED_OP_FLAGS = OCSD_OPFLG_PKTPROC_COMMON; - -/***************************************************************************/ -/*******************ETM V4 INSTRUCTION *************************************/ -/***************************************************************************/ - -TrcPktProcEtmV4I::TrcPktProcEtmV4I() : TrcPktProcBase(ETMV4I_PKTS_NAME), - m_pProcessor(0) -{ - m_supported_op_flags = ETMV4_SUPPORTED_OP_FLAGS; -} - -TrcPktProcEtmV4I::TrcPktProcEtmV4I(int instIDNum) : TrcPktProcBase(ETMV4I_PKTS_NAME, instIDNum), - m_pProcessor(0) -{ - m_supported_op_flags = ETMV4_SUPPORTED_OP_FLAGS; -} - -TrcPktProcEtmV4I::~TrcPktProcEtmV4I() -{ - if(m_pProcessor) - delete m_pProcessor; - m_pProcessor = 0; -} - -ocsd_err_t TrcPktProcEtmV4I::onProtocolConfig() -{ - if(m_pProcessor == 0) - { - m_pProcessor = new (std::nothrow) EtmV4IPktProcImpl(); - if(m_pProcessor == 0) - { - LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_MEM)); - return OCSD_ERR_MEM; - } - m_pProcessor->Initialise(this); - } - return m_pProcessor->Configure(m_config); -} - -ocsd_datapath_resp_t TrcPktProcEtmV4I::processData( const ocsd_trc_index_t index, - const uint32_t dataBlockSize, - const uint8_t *pDataBlock, - uint32_t *numBytesProcessed) -{ - if(m_pProcessor) - return m_pProcessor->processData(index,dataBlockSize,pDataBlock,numBytesProcessed); - return OCSD_RESP_FATAL_NOT_INIT; -} - -ocsd_datapath_resp_t TrcPktProcEtmV4I::onEOT() -{ - if(m_pProcessor) - return m_pProcessor->onEOT(); - return OCSD_RESP_FATAL_NOT_INIT; -} - -ocsd_datapath_resp_t TrcPktProcEtmV4I::onReset() -{ - if(m_pProcessor) - return m_pProcessor->onReset(); - return OCSD_RESP_FATAL_NOT_INIT; -} - -ocsd_datapath_resp_t TrcPktProcEtmV4I::onFlush() -{ - if(m_pProcessor) - return m_pProcessor->onFlush(); - return OCSD_RESP_FATAL_NOT_INIT; -} - -const bool TrcPktProcEtmV4I::isBadPacket() const -{ - if(m_pProcessor) - return m_pProcessor->isBadPacket(); - return false; -} - -/* End of File trc_pkt_proc_etmv4.cpp */ diff --git a/contrib/opencsd/decoder/source/etmv4/trc_pkt_proc_etmv4d_impl.h b/contrib/opencsd/decoder/source/etmv4/trc_pkt_proc_etmv4d_impl.h deleted file mode 100644 index 3be35bd12b55..000000000000 --- a/contrib/opencsd/decoder/source/etmv4/trc_pkt_proc_etmv4d_impl.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * \file trc_pkt_proc_etmv4d_impl.h - * \brief OpenCSD : - * - * \copyright Copyright (c) 2015, 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_PROC_ETMV4D_IMPL_H_INCLUDED -#define ARM_TRC_PKT_PROC_ETMV4D_IMPL_H_INCLUDED - -#include "etmv4/trc_pkt_proc_etmv4.h" -#include "etmv4/trc_cmp_cfg_etmv4.h" - -class EtmV4DPktProcImpl -{ -public: - EtmV4DPktProcImpl(); - ~EtmV4DPktProcImpl(); - - void Initialise(TrcPktProcEtmV4D *p_interface); - - ocsd_err_t Configure(const EtmV4Config *p_config); - - - ocsd_datapath_resp_t processData( const ocsd_trc_index_t index, - const uint32_t dataBlockSize, - const uint8_t *pDataBlock, - uint32_t *numBytesProcessed); - ocsd_datapath_resp_t onEOT(); - ocsd_datapath_resp_t onReset(); - ocsd_datapath_resp_t onFlush(); - -protected: - - bool m_isInit; - TrcPktProcEtmV4D *m_interface; /**< The interface to the other decode components */ - - EtmV4Config m_config; -}; - - -#endif // ARM_TRC_PKT_PROC_ETMV4D_IMPL_H_INCLUDED - -/* End of File trc_pkt_proc_etmv4d_impl.h */ diff --git a/contrib/opencsd/decoder/source/etmv4/trc_pkt_proc_etmv4i_impl.cpp b/contrib/opencsd/decoder/source/etmv4/trc_pkt_proc_etmv4i.cpp similarity index 81% rename from contrib/opencsd/decoder/source/etmv4/trc_pkt_proc_etmv4i_impl.cpp rename to contrib/opencsd/decoder/source/etmv4/trc_pkt_proc_etmv4i.cpp index 0607c192f879..d8c7d84667d1 100644 --- a/contrib/opencsd/decoder/source/etmv4/trc_pkt_proc_etmv4i_impl.cpp +++ b/contrib/opencsd/decoder/source/etmv4/trc_pkt_proc_etmv4i.cpp @@ -1,8 +1,8 @@ /* - * \file trc_pkt_proc_etmv4i_impl.cpp - * \brief OpenCSD : + * \file trc_pkt_proc_etmv4i.cpp + * \brief OpenCSD : Packet processor for ETMv4 * - * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + * \copyright Copyright (c) 2015, 2019, ARM Limited. All Rights Reserved. */ /* @@ -32,87 +32,58 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "trc_pkt_proc_etmv4i_impl.h" +#include "opencsd/etmv4/trc_pkt_proc_etmv4.h" +#include "common/ocsd_error.h" -/* Trace raw input buffer class */ -TraceRawBuffer::TraceRawBuffer() -{ - m_bufSize = 0; - m_bufProcessed = 0; - m_pBuffer = 0; - pkt = 0; -} +#ifdef __GNUC__ + // G++ doesn't like the ## pasting +#define ETMV4I_PKTS_NAME "PKTP_ETMV4I" +#else + // VC++ is fine +#define ETMV4I_PKTS_NAME OCSD_CMPNAME_PREFIX_PKTPROC##"_ETMV4I" +#endif -// init the buffer -void TraceRawBuffer::init(const uint32_t size, const uint8_t *rawtrace, std::vector *out_packet) -{ - m_bufSize = size; - m_bufProcessed = 0; - m_pBuffer = rawtrace; - pkt = out_packet; -} - -void TraceRawBuffer::copyByteToPkt() -{ - if (!empty()) { - pkt->push_back(m_pBuffer[m_bufProcessed]); - m_bufProcessed++; - } -} -uint8_t TraceRawBuffer::peekNextByte() -{ - uint8_t val = 0; - if (!empty()) - val = m_pBuffer[m_bufProcessed]; - return val; -} +static const uint32_t ETMV4_SUPPORTED_OP_FLAGS = OCSD_OPFLG_PKTPROC_COMMON; /* trace etmv4 packet processing class */ -EtmV4IPktProcImpl::EtmV4IPktProcImpl() : +TrcPktProcEtmV4I::TrcPktProcEtmV4I() : TrcPktProcBase(ETMV4I_PKTS_NAME), m_isInit(false), - m_interface(0), m_first_trace_info(false) { - + m_supported_op_flags = ETMV4_SUPPORTED_OP_FLAGS; } -EtmV4IPktProcImpl::~EtmV4IPktProcImpl() +TrcPktProcEtmV4I::TrcPktProcEtmV4I(int instIDNum) : TrcPktProcBase(ETMV4I_PKTS_NAME, instIDNum), + m_isInit(false), + m_first_trace_info(false) +{ + m_supported_op_flags = ETMV4_SUPPORTED_OP_FLAGS; +} + + +TrcPktProcEtmV4I::~TrcPktProcEtmV4I() { } -void EtmV4IPktProcImpl::Initialise(TrcPktProcEtmV4I *p_interface) +ocsd_err_t TrcPktProcEtmV4I::onProtocolConfig() { - if(p_interface) - { - m_interface = p_interface; - m_isInit = true; - } - InitProcessorState(); + InitProcessorState(); + m_config = *TrcPktProcBase::getProtocolConfig(); + BuildIPacketTable(); // packet table based on config + m_isInit = true; + return OCSD_OK; } -ocsd_err_t EtmV4IPktProcImpl::Configure(const EtmV4Config *p_config) -{ - ocsd_err_t err = OCSD_OK; - if(p_config != 0) - { - m_config = *p_config; - BuildIPacketTable(); // packet table based on config - } - else - { - err = OCSD_ERR_INVALID_PARAM_VAL; - if(m_isInit) - m_interface->LogError(ocsdError(OCSD_ERR_SEV_ERROR,err)); - } - return err; -} - -ocsd_datapath_resp_t EtmV4IPktProcImpl::processData( const ocsd_trc_index_t index, +ocsd_datapath_resp_t TrcPktProcEtmV4I::processData( const ocsd_trc_index_t index, const uint32_t dataBlockSize, const uint8_t *pDataBlock, uint32_t *numBytesProcessed) { ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + + if (!m_isInit) + return OCSD_RESP_FATAL_NOT_INIT; + m_trcIn.init(dataBlockSize, pDataBlock, &m_currPacketData); m_blockIndex = index; bool done = false; @@ -122,9 +93,6 @@ ocsd_datapath_resp_t EtmV4IPktProcImpl::processData( const ocsd_trc_index_t ind { try { - /* while (((m_blockBytesProcessed < dataBlockSize) || - ((m_blockBytesProcessed == dataBlockSize) && (m_process_state == SEND_PKT))) && - OCSD_DATA_RESP_IS_CONT(resp))*/ while ( (!m_trcIn.empty() || (m_process_state == SEND_PKT)) && OCSD_DATA_RESP_IS_CONT(resp) ) @@ -142,7 +110,7 @@ ocsd_datapath_resp_t EtmV4IPktProcImpl::processData( const ocsd_trc_index_t ind else { // unsynced - process data until we see a sync point - m_pIPktFn = &EtmV4IPktProcImpl::iNotSync; + m_pIPktFn = &TrcPktProcEtmV4I::iNotSync; m_curr_packet.type = ETM4_PKT_I_NOTSYNC; } m_process_state = PROC_DATA; @@ -153,8 +121,6 @@ ocsd_datapath_resp_t EtmV4IPktProcImpl::processData( const ocsd_trc_index_t ind { nextByte = m_trcIn.peekNextByte(); m_trcIn.copyByteToPkt(); // move next byte into the packet - // m_currPacketData.push_back(pDataBlock[m_blockBytesProcessed]); - // m_blockBytesProcessed++; (this->*m_pIPktFn)(nextByte); } break; @@ -181,7 +147,7 @@ ocsd_datapath_resp_t EtmV4IPktProcImpl::processData( const ocsd_trc_index_t ind catch(ocsdError &err) { done = true; - m_interface->LogError(err); + LogError(err); if( (err.getErrorCode() == OCSD_ERR_BAD_PACKET_SEQ) || (err.getErrorCode() == OCSD_ERR_INVALID_PCKT_HDR)) { @@ -201,7 +167,7 @@ ocsd_datapath_resp_t EtmV4IPktProcImpl::processData( const ocsd_trc_index_t ind /// vv bad at this point. resp = OCSD_RESP_FATAL_SYS_ERR; const ocsdError &fatal = ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_FAIL,m_packet_index,m_config.getTraceID(),"Unknown System Error decoding trace."); - m_interface->LogError(fatal); + LogError(fatal); } } while (!done); @@ -209,9 +175,12 @@ ocsd_datapath_resp_t EtmV4IPktProcImpl::processData( const ocsd_trc_index_t ind return resp; } -ocsd_datapath_resp_t EtmV4IPktProcImpl::onEOT() +ocsd_datapath_resp_t TrcPktProcEtmV4I::onEOT() { ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + if (!m_isInit) + return OCSD_RESP_FATAL_NOT_INIT; + // if we have a partial packet then send to attached sinks if(m_currPacketData.size() != 0) { @@ -222,31 +191,37 @@ ocsd_datapath_resp_t EtmV4IPktProcImpl::onEOT() return resp; } -ocsd_datapath_resp_t EtmV4IPktProcImpl::onReset() +ocsd_datapath_resp_t TrcPktProcEtmV4I::onReset() { + if (!m_isInit) + return OCSD_RESP_FATAL_NOT_INIT; + // prepare for new decoding session InitProcessorState(); return OCSD_RESP_CONT; } -ocsd_datapath_resp_t EtmV4IPktProcImpl::onFlush() +ocsd_datapath_resp_t TrcPktProcEtmV4I::onFlush() { + if (!m_isInit) + return OCSD_RESP_FATAL_NOT_INIT; + // packet processor never holds on to flushable data (may have partial packet, // but any full packets are immediately sent) return OCSD_RESP_CONT; } -void EtmV4IPktProcImpl::InitPacketState() +void TrcPktProcEtmV4I::InitPacketState() { m_currPacketData.clear(); m_curr_packet.initNextPacket(); // clear for next packet. m_update_on_unsync_packet_index = 0; } -void EtmV4IPktProcImpl::InitProcessorState() +void TrcPktProcEtmV4I::InitProcessorState() { InitPacketState(); - m_pIPktFn = &EtmV4IPktProcImpl::iNotSync; + m_pIPktFn = &TrcPktProcEtmV4I::iNotSync; m_packet_index = 0; m_is_sync = false; m_first_trace_info = false; @@ -255,23 +230,23 @@ void EtmV4IPktProcImpl::InitProcessorState() m_curr_packet.initStartState(); } -ocsd_datapath_resp_t EtmV4IPktProcImpl::outputPacket() +ocsd_datapath_resp_t TrcPktProcEtmV4I::outputPacket() { ocsd_datapath_resp_t resp = OCSD_RESP_CONT; - resp = m_interface->outputOnAllInterfaces(m_packet_index,&m_curr_packet,&m_curr_packet.type,m_currPacketData); + resp = outputOnAllInterfaces(m_packet_index,&m_curr_packet,&m_curr_packet.type,m_currPacketData); return resp; } -ocsd_datapath_resp_t EtmV4IPktProcImpl::outputUnsyncedRawPacket() +ocsd_datapath_resp_t TrcPktProcEtmV4I::outputUnsyncedRawPacket() { ocsd_datapath_resp_t resp = OCSD_RESP_CONT; - m_interface->outputRawPacketToMonitor(m_packet_index,&m_curr_packet,m_dump_unsynced_bytes,&m_currPacketData[0]); + outputRawPacketToMonitor(m_packet_index,&m_curr_packet,m_dump_unsynced_bytes,&m_currPacketData[0]); if(!m_sent_notsync_packet) { - resp = m_interface->outputDecodedPacket(m_packet_index,&m_curr_packet); + resp = outputDecodedPacket(m_packet_index,&m_curr_packet); m_sent_notsync_packet = true; } @@ -283,7 +258,7 @@ ocsd_datapath_resp_t EtmV4IPktProcImpl::outputUnsyncedRawPacket() return resp; } -void EtmV4IPktProcImpl::iNotSync(const uint8_t lastByte) +void TrcPktProcEtmV4I::iNotSync(const uint8_t lastByte) { // is it an extension byte? if (lastByte == 0x00) // TBD : add check for forced sync in here? @@ -309,7 +284,7 @@ void EtmV4IPktProcImpl::iNotSync(const uint8_t lastByte) } } -void EtmV4IPktProcImpl::iPktNoPayload(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktNoPayload(const uint8_t lastByte) { // some expansion may be required... switch(m_curr_packet.type) @@ -338,26 +313,26 @@ void EtmV4IPktProcImpl::iPktNoPayload(const uint8_t lastByte) m_process_state = SEND_PKT; // now just send it.... } -void EtmV4IPktProcImpl::iPktReserved(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktReserved(const uint8_t lastByte) { m_curr_packet.updateErrType(ETM4_PKT_I_RESERVED, lastByte); // swap type for err type throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_INVALID_PCKT_HDR,m_packet_index,m_config.getTraceID()); } -void EtmV4IPktProcImpl::iPktInvalidCfg(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktInvalidCfg(const uint8_t lastByte) { m_curr_packet.updateErrType(ETM4_PKT_I_RESERVED_CFG, lastByte); // swap type for err type throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_INVALID_PCKT_HDR, m_packet_index, m_config.getTraceID()); } -void EtmV4IPktProcImpl::iPktExtension(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktExtension(const uint8_t lastByte) { if(m_currPacketData.size() == 2) { // not sync and not next by 0x00 - not sync sequence if(!m_is_sync && (lastByte != 0x00)) { - m_pIPktFn = &EtmV4IPktProcImpl::iNotSync; + m_pIPktFn = &TrcPktProcEtmV4I::iNotSync; m_curr_packet.type = ETM4_PKT_I_NOTSYNC; return; } @@ -376,7 +351,7 @@ void EtmV4IPktProcImpl::iPktExtension(const uint8_t lastByte) case 0x00: m_curr_packet.type = ETM4_PKT_I_ASYNC; - m_pIPktFn = &EtmV4IPktProcImpl::iPktASync; // handle subsequent bytes as async + m_pIPktFn = &TrcPktProcEtmV4I::iPktASync; // handle subsequent bytes as async break; default: @@ -388,14 +363,14 @@ void EtmV4IPktProcImpl::iPktExtension(const uint8_t lastByte) } } -void EtmV4IPktProcImpl::iPktASync(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktASync(const uint8_t lastByte) { if(lastByte != 0x00) { // not sync and not next by 0x00 - not sync sequence if < 12 if(!m_is_sync && m_currPacketData.size() != 12) { - m_pIPktFn = &EtmV4IPktProcImpl::iNotSync; + m_pIPktFn = &TrcPktProcEtmV4I::iNotSync; m_curr_packet.type = ETM4_PKT_I_NOTSYNC; return; } @@ -428,7 +403,7 @@ void EtmV4IPktProcImpl::iPktASync(const uint8_t lastByte) } } -void EtmV4IPktProcImpl::iPktTraceInfo(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktTraceInfo(const uint8_t lastByte) { if(m_currPacketData.size() == 1) // header { @@ -500,7 +475,7 @@ void EtmV4IPktProcImpl::iPktTraceInfo(const uint8_t lastByte) } -void EtmV4IPktProcImpl::iPktTimestamp(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktTimestamp(const uint8_t lastByte) { // process the header byte if(m_currPacketData.size() == 1) @@ -550,7 +525,7 @@ void EtmV4IPktProcImpl::iPktTimestamp(const uint8_t lastByte) } } -void EtmV4IPktProcImpl::iPktException(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktException(const uint8_t lastByte) { uint16_t excep_type = 0; @@ -582,7 +557,7 @@ void EtmV4IPktProcImpl::iPktException(const uint8_t lastByte) } } -void EtmV4IPktProcImpl::iPktCycleCntF123(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktCycleCntF123(const uint8_t lastByte) { ocsd_etmv4_i_pkt_type format = m_curr_packet.type; @@ -657,7 +632,7 @@ void EtmV4IPktProcImpl::iPktCycleCntF123(const uint8_t lastByte) } } -void EtmV4IPktProcImpl::iPktSpeclRes(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktSpeclRes(const uint8_t lastByte) { if(m_currPacketData.size() == 1) { @@ -671,8 +646,10 @@ void EtmV4IPktProcImpl::iPktSpeclRes(const uint8_t lastByte) case 0x2: m_curr_packet.setAtomPacket(ATOM_PATTERN, 0x3, 2); break; // EE case 0x3: m_curr_packet.setAtomPacket(ATOM_PATTERN, 0x0, 1); break; // N } - if(m_curr_packet.getType() == ETM4_PKT_I_CANCEL_F2) + if (m_curr_packet.getType() == ETM4_PKT_I_CANCEL_F2) m_curr_packet.setCancelElements(1); + else + m_curr_packet.setCancelElements(0); m_process_state = SEND_PKT; break; @@ -694,13 +671,12 @@ void EtmV4IPktProcImpl::iPktSpeclRes(const uint8_t lastByte) m_curr_packet.setCommitElements(field_val); else m_curr_packet.setCancelElements(field_val); - // TBD: sanity check with max spec depth here? m_process_state = SEND_PKT; } } } -void EtmV4IPktProcImpl::iPktCondInstr(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktCondInstr(const uint8_t lastByte) { bool bF1Done = false; @@ -740,7 +716,7 @@ void EtmV4IPktProcImpl::iPktCondInstr(const uint8_t lastByte) } } -void EtmV4IPktProcImpl::iPktCondResult(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktCondResult(const uint8_t lastByte) { if(m_currPacketData.size() == 1) { @@ -810,7 +786,7 @@ void EtmV4IPktProcImpl::iPktCondResult(const uint8_t lastByte) } } -void EtmV4IPktProcImpl::iPktContext(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktContext(const uint8_t lastByte) { bool bSendPacket = false; @@ -852,7 +828,7 @@ void EtmV4IPktProcImpl::iPktContext(const uint8_t lastByte) } } -void EtmV4IPktProcImpl::extractAndSetContextInfo(const std::vector &buffer, const int st_idx) +void TrcPktProcEtmV4I::extractAndSetContextInfo(const std::vector &buffer, const int st_idx) { // on input, buffer index points at the info byte - always present uint8_t infoByte = m_currPacketData[st_idx]; @@ -887,7 +863,7 @@ void EtmV4IPktProcImpl::extractAndSetContextInfo(const std::vector &buf } } -void EtmV4IPktProcImpl::iPktAddrCtxt(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktAddrCtxt(const uint8_t lastByte) { if( m_currPacketData.size() == 1) { @@ -955,7 +931,7 @@ void EtmV4IPktProcImpl::iPktAddrCtxt(const uint8_t lastByte) } } -void EtmV4IPktProcImpl::iPktShortAddr(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktShortAddr(const uint8_t lastByte) { if (m_currPacketData.size() == 1) { @@ -980,7 +956,7 @@ void EtmV4IPktProcImpl::iPktShortAddr(const uint8_t lastByte) } } -int EtmV4IPktProcImpl::extractShortAddr(const std::vector &buffer, const int st_idx, const uint8_t IS, uint32_t &value, int &bits) +int TrcPktProcEtmV4I::extractShortAddr(const std::vector &buffer, const int st_idx, const uint8_t IS, uint32_t &value, int &bits) { int IS_shift = (IS == 0) ? 2 : 1; int idx = 0; @@ -1000,7 +976,7 @@ int EtmV4IPktProcImpl::extractShortAddr(const std::vector &buffer, cons return idx; } -void EtmV4IPktProcImpl::iPktLongAddr(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktLongAddr(const uint8_t lastByte) { if(m_currPacketData.size() == 1) { @@ -1044,7 +1020,7 @@ void EtmV4IPktProcImpl::iPktLongAddr(const uint8_t lastByte) } } -void EtmV4IPktProcImpl::iPktQ(const uint8_t lastByte) +void TrcPktProcEtmV4I::iPktQ(const uint8_t lastByte) { if(m_currPacketData.size() == 1) { @@ -1096,7 +1072,7 @@ void EtmV4IPktProcImpl::iPktQ(const uint8_t lastByte) default: m_curr_packet.err_type = m_curr_packet.type; m_curr_packet.type = ETM4_PKT_I_BAD_SEQUENCE; - //SendBadIPacket( PKT_BAD_SEQUENCE, "ERROR: Bad Q packet type", PKT_Q ); + m_process_state = SEND_PKT; break; } } @@ -1156,7 +1132,7 @@ void EtmV4IPktProcImpl::iPktQ(const uint8_t lastByte) } -void EtmV4IPktProcImpl::iAtom(const uint8_t lastByte) +void TrcPktProcEtmV4I::iAtom(const uint8_t lastByte) { // patterns lsbit = oldest atom, ms bit = newest. static const uint32_t f4_patterns[] = { @@ -1228,32 +1204,32 @@ void EtmV4IPktProcImpl::iAtom(const uint8_t lastByte) } // header byte processing is table driven. -void EtmV4IPktProcImpl::BuildIPacketTable() +void TrcPktProcEtmV4I::BuildIPacketTable() { // initialise everything as reserved. for(int i = 0; i < 256; i++) { m_i_table[i].pkt_type = ETM4_PKT_I_RESERVED; - m_i_table[i].pptkFn = &EtmV4IPktProcImpl::iPktReserved; + m_i_table[i].pptkFn = &TrcPktProcEtmV4I::iPktReserved; } // 0x00 - extension m_i_table[0x00].pkt_type = ETM4_PKT_I_EXTENSION; - m_i_table[0x00].pptkFn = &EtmV4IPktProcImpl::iPktExtension; + m_i_table[0x00].pptkFn = &TrcPktProcEtmV4I::iPktExtension; // 0x01 - Trace info m_i_table[0x01].pkt_type = ETM4_PKT_I_TRACE_INFO; - m_i_table[0x01].pptkFn = &EtmV4IPktProcImpl::iPktTraceInfo; + m_i_table[0x01].pptkFn = &TrcPktProcEtmV4I::iPktTraceInfo; // b0000001x - timestamp m_i_table[0x02].pkt_type = ETM4_PKT_I_TIMESTAMP; - m_i_table[0x02].pptkFn = &EtmV4IPktProcImpl::iPktTimestamp; + m_i_table[0x02].pptkFn = &TrcPktProcEtmV4I::iPktTimestamp; m_i_table[0x03].pkt_type = ETM4_PKT_I_TIMESTAMP; - m_i_table[0x03].pptkFn = &EtmV4IPktProcImpl::iPktTimestamp; + m_i_table[0x03].pptkFn = &TrcPktProcEtmV4I::iPktTimestamp; // b0000 0100 - trace on m_i_table[0x04].pkt_type = ETM4_PKT_I_TRACE_ON; - m_i_table[0x04].pptkFn = &EtmV4IPktProcImpl::iPktNoPayload; + m_i_table[0x04].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload; // b0000 0101 - Funct ret V8M @@ -1262,30 +1238,30 @@ void EtmV4IPktProcImpl::BuildIPacketTable() (OCSD_IS_V8_ARCH(m_config.archVersion())) && (m_config.FullVersion() >= 0x42)) { - m_i_table[0x05].pptkFn = &EtmV4IPktProcImpl::iPktNoPayload; + m_i_table[0x05].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload; } // b0000 0110 - exception m_i_table[0x06].pkt_type = ETM4_PKT_I_EXCEPT; - m_i_table[0x06].pptkFn = &EtmV4IPktProcImpl::iPktException; + m_i_table[0x06].pptkFn = &TrcPktProcEtmV4I::iPktException; // b0000 0111 - exception return m_i_table[0x07].pkt_type = ETM4_PKT_I_EXCEPT_RTN; - m_i_table[0x07].pptkFn = &EtmV4IPktProcImpl::iPktNoPayload; + m_i_table[0x07].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload; // b0000 110x - cycle count f2 // b0000 111x - cycle count f1 for(int i = 0; i < 4; i++) { m_i_table[0x0C+i].pkt_type = (i >= 2) ? ETM4_PKT_I_CCNT_F1 : ETM4_PKT_I_CCNT_F2; - m_i_table[0x0C+i].pptkFn = &EtmV4IPktProcImpl::iPktCycleCntF123; + m_i_table[0x0C+i].pptkFn = &TrcPktProcEtmV4I::iPktCycleCntF123; } // b0001 xxxx - cycle count f3 for(int i = 0; i < 16; i++) { m_i_table[0x10+i].pkt_type = ETM4_PKT_I_CCNT_F3; - m_i_table[0x10+i].pptkFn = &EtmV4IPktProcImpl::iPktCycleCntF123; + m_i_table[0x10+i].pptkFn = &TrcPktProcEtmV4I::iPktCycleCntF123; } // b0010 0xxx - NDSM @@ -1293,9 +1269,9 @@ void EtmV4IPktProcImpl::BuildIPacketTable() { m_i_table[0x20 + i].pkt_type = ETM4_PKT_I_NUM_DS_MKR; if (m_config.enabledDataTrace()) - m_i_table[0x20+i].pptkFn = &EtmV4IPktProcImpl::iPktNoPayload; + m_i_table[0x20+i].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload; else - m_i_table[0x20+i].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg; + m_i_table[0x20+i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg; } // b0010 10xx, b0010 1100 - UDSM @@ -1303,43 +1279,40 @@ void EtmV4IPktProcImpl::BuildIPacketTable() { m_i_table[0x28+i].pkt_type = ETM4_PKT_I_UNNUM_DS_MKR; if (m_config.enabledDataTrace()) - m_i_table[0x28+i].pptkFn = &EtmV4IPktProcImpl::iPktNoPayload; + m_i_table[0x28+i].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload; else - m_i_table[0x28+i].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg; + m_i_table[0x28+i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg; } // b0010 1101 - commit m_i_table[0x2D].pkt_type = ETM4_PKT_I_COMMIT; - m_i_table[0x2D].pptkFn = &EtmV4IPktProcImpl::iPktSpeclRes; + m_i_table[0x2D].pptkFn = &TrcPktProcEtmV4I::iPktSpeclRes; - // b0010 111x - cancel f1 - for(int i = 0; i < 2; i++) - { - // G++ doesn't understand [0x2E+i] so... - int idx = i + 0x2E; - m_i_table[idx].pkt_type = ETM4_PKT_I_CANCEL_F1; - m_i_table[idx].pptkFn = &EtmV4IPktProcImpl::iPktSpeclRes; - } + // b0010 111x - cancel f1 (mis pred) + m_i_table[0x2E].pkt_type = ETM4_PKT_I_CANCEL_F1; + m_i_table[0x2E].pptkFn = &TrcPktProcEtmV4I::iPktSpeclRes; + m_i_table[0x2F].pkt_type = ETM4_PKT_I_CANCEL_F1_MISPRED; + m_i_table[0x2F].pptkFn = &TrcPktProcEtmV4I::iPktSpeclRes; // b0011 00xx - mis predict for(int i = 0; i < 4; i++) { m_i_table[0x30+i].pkt_type = ETM4_PKT_I_MISPREDICT; - m_i_table[0x30+i].pptkFn = &EtmV4IPktProcImpl::iPktSpeclRes; + m_i_table[0x30+i].pptkFn = &TrcPktProcEtmV4I::iPktSpeclRes; } // b0011 01xx - cancel f2 for(int i = 0; i < 4; i++) { m_i_table[0x34+i].pkt_type = ETM4_PKT_I_CANCEL_F2; - m_i_table[0x34+i].pptkFn = &EtmV4IPktProcImpl::iPktSpeclRes; + m_i_table[0x34+i].pptkFn = &TrcPktProcEtmV4I::iPktSpeclRes; } // b0011 1xxx - cancel f3 for(int i = 0; i < 8; i++) { m_i_table[0x38+i].pkt_type = ETM4_PKT_I_CANCEL_F3; - m_i_table[0x38+i].pptkFn = &EtmV4IPktProcImpl::iPktSpeclRes; + m_i_table[0x38+i].pptkFn = &TrcPktProcEtmV4I::iPktSpeclRes; } bool bCondValid = m_config.hasCondTrace() && m_config.enabledCondITrace(); @@ -1349,26 +1322,26 @@ void EtmV4IPktProcImpl::BuildIPacketTable() { m_i_table[0x40 + i].pkt_type = ETM4_PKT_I_COND_I_F2; if (bCondValid) - m_i_table[0x40 + i].pptkFn = &EtmV4IPktProcImpl::iPktCondInstr; + m_i_table[0x40 + i].pptkFn = &TrcPktProcEtmV4I::iPktCondInstr; else - m_i_table[0x40 + i].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg; + m_i_table[0x40 + i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg; } // b0100 0011 - cond flush m_i_table[0x43].pkt_type = ETM4_PKT_I_COND_FLUSH; if (bCondValid) - m_i_table[0x43].pptkFn = &EtmV4IPktProcImpl::iPktNoPayload; + m_i_table[0x43].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload; else - m_i_table[0x43].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg; + m_i_table[0x43].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg; // b0100 010x, b0100 0110 - cond res f4 for (int i = 0; i < 3; i++) { m_i_table[0x44 + i].pkt_type = ETM4_PKT_I_COND_RES_F4; if (bCondValid) - m_i_table[0x44 + i].pptkFn = &EtmV4IPktProcImpl::iPktCondResult; + m_i_table[0x44 + i].pptkFn = &TrcPktProcEtmV4I::iPktCondResult; else - m_i_table[0x44 + i].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg; + m_i_table[0x44 + i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg; } // b0100 100x, b0100 0110 - cond res f2 @@ -1377,17 +1350,17 @@ void EtmV4IPktProcImpl::BuildIPacketTable() { m_i_table[0x48 + i].pkt_type = ETM4_PKT_I_COND_RES_F2; if (bCondValid) - m_i_table[0x48 + i].pptkFn = &EtmV4IPktProcImpl::iPktCondResult; + m_i_table[0x48 + i].pptkFn = &TrcPktProcEtmV4I::iPktCondResult; else - m_i_table[0x48 + i].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg; + m_i_table[0x48 + i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg; } for (int i = 0; i < 3; i++) { m_i_table[0x4C + i].pkt_type = ETM4_PKT_I_COND_RES_F2; if (bCondValid) - m_i_table[0x4C + i].pptkFn = &EtmV4IPktProcImpl::iPktCondResult; + m_i_table[0x4C + i].pptkFn = &TrcPktProcEtmV4I::iPktCondResult; else - m_i_table[0x4C + i].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg; + m_i_table[0x4C + i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg; } // b0101xxxx - cond res f3 @@ -1395,9 +1368,9 @@ void EtmV4IPktProcImpl::BuildIPacketTable() { m_i_table[0x50 + i].pkt_type = ETM4_PKT_I_COND_RES_F3; if (bCondValid) - m_i_table[0x50 + i].pptkFn = &EtmV4IPktProcImpl::iPktCondResult; + m_i_table[0x50 + i].pptkFn = &TrcPktProcEtmV4I::iPktCondResult; else - m_i_table[0x50 + i].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg; + m_i_table[0x50 + i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg; } // b011010xx - cond res f1 @@ -1405,24 +1378,24 @@ void EtmV4IPktProcImpl::BuildIPacketTable() { m_i_table[0x68 + i].pkt_type = ETM4_PKT_I_COND_RES_F1; if (bCondValid) - m_i_table[0x68 + i].pptkFn = &EtmV4IPktProcImpl::iPktCondResult; + m_i_table[0x68 + i].pptkFn = &TrcPktProcEtmV4I::iPktCondResult; else - m_i_table[0x68 + i].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg; + m_i_table[0x68 + i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg; } // b0110 1100 - cond instr f1 m_i_table[0x6C].pkt_type = ETM4_PKT_I_COND_I_F1; if (bCondValid) - m_i_table[0x6C].pptkFn = &EtmV4IPktProcImpl::iPktCondInstr; + m_i_table[0x6C].pptkFn = &TrcPktProcEtmV4I::iPktCondInstr; else - m_i_table[0x6C].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg; + m_i_table[0x6C].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg; // b0110 1101 - cond instr f3 m_i_table[0x6D].pkt_type = ETM4_PKT_I_COND_I_F3; if (bCondValid) - m_i_table[0x6D].pptkFn = &EtmV4IPktProcImpl::iPktCondInstr; + m_i_table[0x6D].pptkFn = &TrcPktProcEtmV4I::iPktCondInstr; else - m_i_table[0x6D].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg; + m_i_table[0x6D].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg; // b0110111x - cond res f1 for (int i = 0; i < 2; i++) @@ -1430,30 +1403,30 @@ void EtmV4IPktProcImpl::BuildIPacketTable() // G++ cannot understand [0x6E+i] so change these round m_i_table[i + 0x6E].pkt_type = ETM4_PKT_I_COND_RES_F1; if (bCondValid) - m_i_table[i + 0x6E].pptkFn = &EtmV4IPktProcImpl::iPktCondResult; + m_i_table[i + 0x6E].pptkFn = &TrcPktProcEtmV4I::iPktCondResult; else - m_i_table[i + 0x6E].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg; + m_i_table[i + 0x6E].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg; } // ETM 4.3 introduces ignore packets if (m_config.FullVersion() >= 0x43) { m_i_table[0x70].pkt_type = ETM4_PKT_I_IGNORE; - m_i_table[0x70].pptkFn = &EtmV4IPktProcImpl::iPktNoPayload; + m_i_table[0x70].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload; } // b01110001 - b01111111 - event trace for(int i = 0; i < 15; i++) { m_i_table[0x71+i].pkt_type = ETM4_PKT_I_EVENT; - m_i_table[0x71+i].pptkFn = &EtmV4IPktProcImpl::iPktNoPayload; + m_i_table[0x71+i].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload; } // 0b1000 000x - context for(int i = 0; i < 2; i++) { m_i_table[0x80+i].pkt_type = ETM4_PKT_I_CTXT; - m_i_table[0x80+i].pptkFn = &EtmV4IPktProcImpl::iPktContext; + m_i_table[0x80+i].pptkFn = &TrcPktProcEtmV4I::iPktContext; } // 0b1000 0010 to b1000 0011 - addr with ctxt @@ -1461,27 +1434,27 @@ void EtmV4IPktProcImpl::BuildIPacketTable() for(int i = 0; i < 2; i++) { m_i_table[0x82+i].pkt_type = (i == 0) ? ETM4_PKT_I_ADDR_CTXT_L_32IS0 : ETM4_PKT_I_ADDR_CTXT_L_32IS1; - m_i_table[0x82+i].pptkFn = &EtmV4IPktProcImpl::iPktAddrCtxt; + m_i_table[0x82+i].pptkFn = &TrcPktProcEtmV4I::iPktAddrCtxt; } for(int i = 0; i < 2; i++) { m_i_table[0x85+i].pkt_type = (i == 0) ? ETM4_PKT_I_ADDR_CTXT_L_64IS0 : ETM4_PKT_I_ADDR_CTXT_L_64IS1; - m_i_table[0x85+i].pptkFn = &EtmV4IPktProcImpl::iPktAddrCtxt; + m_i_table[0x85+i].pptkFn = &TrcPktProcEtmV4I::iPktAddrCtxt; } // 0b1001 0000 to b1001 0010 - exact match addr for(int i = 0; i < 3; i++) { m_i_table[0x90+i].pkt_type = ETM4_PKT_I_ADDR_MATCH; - m_i_table[0x90+i].pptkFn = &EtmV4IPktProcImpl::iPktNoPayload; + m_i_table[0x90+i].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload; } // b1001 0101 - b1001 0110 - addr short address for(int i = 0; i < 2; i++) { m_i_table[0x95+i].pkt_type = (i == 0) ? ETM4_PKT_I_ADDR_S_IS0 : ETM4_PKT_I_ADDR_S_IS1; - m_i_table[0x95+i].pptkFn = &EtmV4IPktProcImpl::iPktShortAddr; + m_i_table[0x95+i].pptkFn = &TrcPktProcEtmV4I::iPktShortAddr; } // b10011010 - b10011011 - addr long address @@ -1489,12 +1462,12 @@ void EtmV4IPktProcImpl::BuildIPacketTable() for(int i = 0; i < 2; i++) { m_i_table[0x9A+i].pkt_type = (i == 0) ? ETM4_PKT_I_ADDR_L_32IS0 : ETM4_PKT_I_ADDR_L_32IS1; - m_i_table[0x9A+i].pptkFn = &EtmV4IPktProcImpl::iPktLongAddr; + m_i_table[0x9A+i].pptkFn = &TrcPktProcEtmV4I::iPktLongAddr; } for(int i = 0; i < 2; i++) { m_i_table[0x9D+i].pkt_type = (i == 0) ? ETM4_PKT_I_ADDR_L_64IS0 : ETM4_PKT_I_ADDR_L_64IS1; - m_i_table[0x9D+i].pptkFn = &EtmV4IPktProcImpl::iPktLongAddr; + m_i_table[0x9D+i].pptkFn = &TrcPktProcEtmV4I::iPktLongAddr; } // b1010xxxx - Q packet @@ -1515,7 +1488,7 @@ void EtmV4IPktProcImpl::BuildIPacketTable() default: // if this config supports Q elem - otherwise reserved again. if (m_config.hasQElem()) - m_i_table[0xA0 + i].pptkFn = &EtmV4IPktProcImpl::iPktQ; + m_i_table[0xA0 + i].pptkFn = &TrcPktProcEtmV4I::iPktQ; } } @@ -1523,46 +1496,46 @@ void EtmV4IPktProcImpl::BuildIPacketTable() for(int i = 0xC0; i <= 0xD4; i++) // atom f6 { m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F6; - m_i_table[i].pptkFn = &EtmV4IPktProcImpl::iAtom; + m_i_table[i].pptkFn = &TrcPktProcEtmV4I::iAtom; } for(int i = 0xD5; i <= 0xD7; i++) // atom f5 { m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F5; - m_i_table[i].pptkFn = &EtmV4IPktProcImpl::iAtom; + m_i_table[i].pptkFn = &TrcPktProcEtmV4I::iAtom; } for(int i = 0xD8; i <= 0xDB; i++) // atom f2 { m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F2; - m_i_table[i].pptkFn = &EtmV4IPktProcImpl::iAtom; + m_i_table[i].pptkFn = &TrcPktProcEtmV4I::iAtom; } for(int i = 0xDC; i <= 0xDF; i++) // atom f4 { m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F4; - m_i_table[i].pptkFn = &EtmV4IPktProcImpl::iAtom; + m_i_table[i].pptkFn = &TrcPktProcEtmV4I::iAtom; } for(int i = 0xE0; i <= 0xF4; i++) // atom f6 { m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F6; - m_i_table[i].pptkFn = &EtmV4IPktProcImpl::iAtom; + m_i_table[i].pptkFn = &TrcPktProcEtmV4I::iAtom; } // atom f5 m_i_table[0xF5].pkt_type = ETM4_PKT_I_ATOM_F5; - m_i_table[0xF5].pptkFn = &EtmV4IPktProcImpl::iAtom; + m_i_table[0xF5].pptkFn = &TrcPktProcEtmV4I::iAtom; for(int i = 0xF6; i <= 0xF7; i++) // atom f1 { m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F1; - m_i_table[i].pptkFn = &EtmV4IPktProcImpl::iAtom; + m_i_table[i].pptkFn = &TrcPktProcEtmV4I::iAtom; } for(int i = 0xF8; i <= 0xFF; i++) // atom f3 { m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F3; - m_i_table[i].pptkFn = &EtmV4IPktProcImpl::iAtom; + m_i_table[i].pptkFn = &TrcPktProcEtmV4I::iAtom; } } - unsigned EtmV4IPktProcImpl::extractContField(const std::vector &buffer, const unsigned st_idx, uint32_t &value, const unsigned byte_limit /*= 5*/) + unsigned TrcPktProcEtmV4I::extractContField(const std::vector &buffer, const unsigned st_idx, uint32_t &value, const unsigned byte_limit /*= 5*/) { unsigned idx = 0; bool lastByte = false; @@ -1586,7 +1559,7 @@ void EtmV4IPktProcImpl::BuildIPacketTable() return idx; } -unsigned EtmV4IPktProcImpl::extractContField64(const std::vector &buffer, const unsigned st_idx, uint64_t &value, const unsigned byte_limit /*= 9*/) +unsigned TrcPktProcEtmV4I::extractContField64(const std::vector &buffer, const unsigned st_idx, uint64_t &value, const unsigned byte_limit /*= 9*/) { unsigned idx = 0; bool lastByte = false; @@ -1610,7 +1583,7 @@ unsigned EtmV4IPktProcImpl::extractContField64(const std::vector &buffe return idx; } - unsigned EtmV4IPktProcImpl::extractCondResult(const std::vector &buffer, const unsigned st_idx, uint32_t& key, uint8_t &result) + unsigned TrcPktProcEtmV4I::extractCondResult(const std::vector &buffer, const unsigned st_idx, uint32_t& key, uint8_t &result) { unsigned idx = 0; bool lastByte = false; @@ -1644,7 +1617,7 @@ unsigned EtmV4IPktProcImpl::extractContField64(const std::vector &buffe return idx; } -int EtmV4IPktProcImpl::extract64BitLongAddr(const std::vector &buffer, const int st_idx, const uint8_t IS, uint64_t &value) +int TrcPktProcEtmV4I::extract64BitLongAddr(const std::vector &buffer, const int st_idx, const uint8_t IS, uint64_t &value) { value = 0; if(IS == 0) @@ -1666,7 +1639,7 @@ int EtmV4IPktProcImpl::extract64BitLongAddr(const std::vector &buffer, return 8; } -int EtmV4IPktProcImpl::extract32BitLongAddr(const std::vector &buffer, const int st_idx, const uint8_t IS, uint32_t &value) +int TrcPktProcEtmV4I::extract32BitLongAddr(const std::vector &buffer, const int st_idx, const uint8_t IS, uint32_t &value) { value = 0; if(IS == 0) @@ -1684,11 +1657,11 @@ int EtmV4IPktProcImpl::extract32BitLongAddr(const std::vector &buffer, return 4; } -void EtmV4IPktProcImpl::throwBadSequenceError(const char *pszExtMsg) +void TrcPktProcEtmV4I::throwBadSequenceError(const char *pszExtMsg) { m_curr_packet.updateErrType(ETM4_PKT_I_BAD_SEQUENCE); // swap type for err type throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_BAD_PACKET_SEQ,m_packet_index,m_config.getTraceID(),pszExtMsg); } -/* End of File trc_pkt_proc_etmv4i_impl.cpp */ +/* End of File trc_pkt_proc_etmv4i.cpp */ 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 ab93284848bb..614fc1d8b45c 100644 --- a/contrib/opencsd/decoder/source/i_dec/trc_i_decode.cpp +++ b/contrib/opencsd/decoder/source/i_dec/trc_i_decode.cpp @@ -39,21 +39,23 @@ ocsd_err_t TrcIDecode::DecodeInstruction(ocsd_instr_info *instr_info) { ocsd_err_t err = OCSD_OK; - clear_instr_subtype(); - SetArchVersion(instr_info); + struct decode_info info; + + info.instr_sub_type = OCSD_S_INSTR_NONE; + info.arch_version = (uint16_t)(instr_info->pe_type.arch); switch(instr_info->isa) { case ocsd_isa_arm: - err = DecodeA32(instr_info); + err = DecodeA32(instr_info, &info); break; case ocsd_isa_thumb2: - err = DecodeT32(instr_info); + err = DecodeT32(instr_info, &info); break; case ocsd_isa_aarch64: - err = DecodeA64(instr_info); + err = DecodeA64(instr_info, &info); break; case ocsd_isa_tee: @@ -63,27 +65,11 @@ ocsd_err_t TrcIDecode::DecodeInstruction(ocsd_instr_info *instr_info) err = OCSD_ERR_UNSUPPORTED_ISA; break; } - instr_info->sub_type = get_instr_subtype(); + instr_info->sub_type = info.instr_sub_type; return err; } -void TrcIDecode::SetArchVersion(ocsd_instr_info *instr_info) -{ - uint16_t arch = 0x0700; - - switch (instr_info->pe_type.arch) - { - case ARCH_V8: arch = 0x0800; break; - case ARCH_V8r3: arch = 0x0803; break; - case ARCH_V7: - default: - break; - } - set_arch_version(arch); -} - - -ocsd_err_t TrcIDecode::DecodeA32(ocsd_instr_info *instr_info) +ocsd_err_t TrcIDecode::DecodeA32(ocsd_instr_info *instr_info, struct decode_info *info) { uint32_t branchAddr = 0; arm_barrier_t barrier; @@ -93,10 +79,10 @@ ocsd_err_t TrcIDecode::DecodeA32(ocsd_instr_info *instr_info) instr_info->next_isa = instr_info->isa; // assume same ISA instr_info->is_link = 0; - if(inst_ARM_is_indirect_branch(instr_info->opcode)) + if(inst_ARM_is_indirect_branch(instr_info->opcode, info)) { instr_info->type = OCSD_INSTR_BR_INDIRECT; - instr_info->is_link = inst_ARM_is_branch_and_link(instr_info->opcode); + instr_info->is_link = inst_ARM_is_branch_and_link(instr_info->opcode, info); } else if(inst_ARM_is_direct_branch(instr_info->opcode)) { @@ -108,7 +94,7 @@ ocsd_err_t TrcIDecode::DecodeA32(ocsd_instr_info *instr_info) branchAddr &= ~0x1; } instr_info->branch_addr = (ocsd_vaddr_t)branchAddr; - instr_info->is_link = inst_ARM_is_branch_and_link(instr_info->opcode); + instr_info->is_link = inst_ARM_is_branch_and_link(instr_info->opcode, info); } else if((barrier = inst_ARM_barrier(instr_info->opcode)) != ARM_BARRIER_NONE) { @@ -137,7 +123,7 @@ ocsd_err_t TrcIDecode::DecodeA32(ocsd_instr_info *instr_info) return OCSD_OK; } -ocsd_err_t TrcIDecode::DecodeA64(ocsd_instr_info *instr_info) +ocsd_err_t TrcIDecode::DecodeA64(ocsd_instr_info *instr_info, struct decode_info *info) { uint64_t branchAddr = 0; arm_barrier_t barrier; @@ -147,12 +133,12 @@ ocsd_err_t TrcIDecode::DecodeA64(ocsd_instr_info *instr_info) instr_info->next_isa = instr_info->isa; // assume same ISA instr_info->is_link = 0; - if(inst_A64_is_indirect_branch_link(instr_info->opcode, &instr_info->is_link)) + 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)) + 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; @@ -187,7 +173,7 @@ ocsd_err_t TrcIDecode::DecodeA64(ocsd_instr_info *instr_info) return OCSD_OK; } -ocsd_err_t TrcIDecode::DecodeT32(ocsd_instr_info *instr_info) +ocsd_err_t TrcIDecode::DecodeT32(ocsd_instr_info *instr_info, struct decode_info *info) { uint32_t branchAddr = 0; arm_barrier_t barrier; @@ -206,7 +192,7 @@ ocsd_err_t TrcIDecode::DecodeT32(ocsd_instr_info *instr_info) instr_info->is_conditional = 0; - if(inst_Thumb_is_direct_branch_link(instr_info->opcode,&instr_info->is_link, &instr_info->is_conditional)) + if(inst_Thumb_is_direct_branch_link(instr_info->opcode,&instr_info->is_link, &instr_info->is_conditional, info)) { inst_Thumb_branch_destination((uint32_t)instr_info->instr_addr,instr_info->opcode,&branchAddr); instr_info->type = OCSD_INSTR_BR; @@ -214,7 +200,7 @@ ocsd_err_t TrcIDecode::DecodeT32(ocsd_instr_info *instr_info) if((branchAddr & 0x1) == 0) instr_info->next_isa = ocsd_isa_arm; } - else if (inst_Thumb_is_indirect_branch_link(instr_info->opcode, &instr_info->is_link)) + else if (inst_Thumb_is_indirect_branch_link(instr_info->opcode, &instr_info->is_link, info)) { instr_info->type = OCSD_INSTR_BR_INDIRECT; } @@ -246,5 +232,4 @@ ocsd_err_t TrcIDecode::DecodeT32(ocsd_instr_info *instr_info) return OCSD_OK; } - /* End of File trc_i_decode.cpp */ 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 09964a15e7b3..3652e84921f3 100644 --- a/contrib/opencsd/decoder/source/i_dec/trc_idec_arminst.cpp +++ b/contrib/opencsd/decoder/source/i_dec/trc_idec_arminst.cpp @@ -42,27 +42,6 @@ block identification and trace decode. #include /* for NULL */ #include - -static ocsd_instr_subtype instr_sub_type = OCSD_S_INSTR_NONE; - -/* need to spot the architecture version for certain instructions */ -static uint16_t arch_version = 0x70; - -ocsd_instr_subtype get_instr_subtype() -{ - return instr_sub_type; -} - -void clear_instr_subtype() -{ - instr_sub_type = OCSD_S_INSTR_NONE; -} - -void set_arch_version(uint16_t version) -{ - arch_version = version; -} - int inst_ARM_is_direct_branch(uint32_t inst) { int is_direct_branch = 1; @@ -91,7 +70,7 @@ int inst_ARM_wfiwfe(uint32_t inst) return 0; } -int inst_ARM_is_indirect_branch(uint32_t inst) +int inst_ARM_is_indirect_branch(uint32_t inst, struct decode_info *info) { int is_indirect_branch = 1; if ((inst & 0xf0000000) == 0xf0000000) { @@ -104,23 +83,23 @@ int inst_ARM_is_indirect_branch(uint32_t inst) } else if ((inst & 0x0ff000d0) == 0x01200010) { /* BLX (register), BX */ if ((inst & 0xFF) == 0x1E) - instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* BX LR */ + info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* BX LR */ } else if ((inst & 0x0ff000f0) == 0x01200020) { /* BXJ: in v8 this behaves like BX */ } else if ((inst & 0x0e108000) == 0x08108000) { /* POP {...,pc} or LDMxx {...,pc} */ if ((inst & 0x0FFFA000) == 0x08BD8000) /* LDMIA SP!,{...,pc} */ - instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; + info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; } else if ((inst & 0x0e50f000) == 0x0410f000) { /* LDR PC,imm... inc. POP {PC} */ if ( (inst & 0x01ff0000) == 0x009D0000) - instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* LDR PC, [SP], #imm */ + info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* LDR PC, [SP], #imm */ } else if ((inst & 0x0e50f010) == 0x0610f000) { /* LDR PC,reg */ } else if ((inst & 0x0fe0f000) == 0x01a0f000) { /* MOV PC,rx */ if ((inst & 0x00100FFF) == 0x00E) /* ensure the S=0, LSL #0 variant - i.e plain MOV */ - instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* MOV PC, R14 */ + info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* MOV PC, R14 */ } else if ((inst & 0x0f900080) == 0x01000000) { /* "Miscellaneous instructions" - in DP space */ is_indirect_branch = 0; @@ -144,13 +123,13 @@ int inst_ARM_is_indirect_branch(uint32_t inst) return is_indirect_branch; } -int inst_Thumb_is_direct_branch(uint32_t inst) +int inst_Thumb_is_direct_branch(uint32_t inst, struct decode_info *info) { uint8_t link, cond; - return inst_Thumb_is_direct_branch_link(inst, &link, &cond); + return inst_Thumb_is_direct_branch_link(inst, &link, &cond, info); } -int inst_Thumb_is_direct_branch_link(uint32_t inst, uint8_t *is_link, uint8_t *is_cond) +int inst_Thumb_is_direct_branch_link(uint32_t inst, uint8_t *is_link, uint8_t *is_cond, struct decode_info *info) { int is_direct_branch = 1; @@ -166,12 +145,12 @@ int inst_Thumb_is_direct_branch_link(uint32_t inst, uint8_t *is_link, uint8_t *i /* B (encoding T4); BL (encoding T1) */ if (inst & 0x00004000) { *is_link = 1; - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; } } else if ((inst & 0xf800d001) == 0xf000c000) { /* BLX (imm) (encoding T2) */ *is_link = 1; - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; } else if ((inst & 0xf5000000) == 0xb1000000) { /* CB(NZ) */ *is_cond = 1; @@ -197,13 +176,13 @@ int inst_Thumb_wfiwfe(uint32_t inst) return is_wfiwfe; } -int inst_Thumb_is_indirect_branch(uint32_t inst) +int inst_Thumb_is_indirect_branch(uint32_t inst, struct decode_info *info) { uint8_t link; - return inst_Thumb_is_indirect_branch_link(inst, &link); + return inst_Thumb_is_indirect_branch_link(inst, &link, info); } -int inst_Thumb_is_indirect_branch_link(uint32_t inst, uint8_t *is_link) +int inst_Thumb_is_indirect_branch_link(uint32_t inst, uint8_t *is_link, struct decode_info *info) { /* See e.g. PFT Table 2-3 and Table 2-5 */ int is_branch = 1; @@ -212,20 +191,20 @@ int inst_Thumb_is_indirect_branch_link(uint32_t inst, uint8_t *is_link) /* BX, BLX (reg) [v8M includes BXNS, BLXNS] */ if (inst & 0x00800000) { *is_link = 1; - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; } else if ((inst & 0x00780000) == 0x00700000) { - instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* BX LR */ + info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* BX LR */ } } else if ((inst & 0xfff0d000) == 0xf3c08000) { /* BXJ: in v8 this behaves like BX */ } else if ((inst & 0xff000000) == 0xbd000000) { /* POP {pc} */ - instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; + info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; } else if ((inst & 0xfd870000) == 0x44870000) { /* MOV PC,reg or ADD PC,reg */ - if ((inst & 0xffff0000) == 0x46f700000) - instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* MOV PC,LR */ + if ((inst & 0xffff0000) == 0x46f70000) + info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* MOV PC,LR */ } else if ((inst & 0xfff0ffe0) == 0xe8d0f000) { /* TBB/TBH */ } else if ((inst & 0xffd00000) == 0xe8100000) { @@ -241,26 +220,26 @@ int inst_Thumb_is_indirect_branch_link(uint32_t inst, uint8_t *is_link) } else if ((inst & 0xfff0f800) == 0xf850f800) { /* LDR PC,imm (T4) */ if((inst & 0x000f0f00) == 0x000d0b00) - instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* LDR PC, [SP], #imm*/ + info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* LDR PC, [SP], #imm*/ } else if ((inst & 0xfff0ffc0) == 0xf850f000) { /* LDR PC,reg (T2) */ } else if ((inst & 0xfe508000) == 0xe8108000) { /* LDM PC */ if ((inst & 0x0FFF0000) == 0x08BD0000) /* LDMIA [SP]!, */ - instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* POP {...,pc} */ + info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* POP {...,pc} */ } else { is_branch = 0; } return is_branch; } -int inst_A64_is_direct_branch(uint32_t inst) +int inst_A64_is_direct_branch(uint32_t inst, struct decode_info *info) { uint8_t link = 0; - return inst_A64_is_direct_branch_link(inst, &link); + return inst_A64_is_direct_branch_link(inst, &link, info); } -int inst_A64_is_direct_branch_link(uint32_t inst, uint8_t *is_link) +int inst_A64_is_direct_branch_link(uint32_t inst, uint8_t *is_link, struct decode_info *info) { int is_direct_branch = 1; if ((inst & 0x7c000000) == 0x34000000) { @@ -271,7 +250,7 @@ int inst_A64_is_direct_branch_link(uint32_t inst, uint8_t *is_link) /* B, BL imm */ if (inst & 0x80000000) { *is_link = 1; - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; } } else { is_direct_branch = 0; @@ -287,13 +266,13 @@ int inst_A64_wfiwfe(uint32_t inst) return 0; } -int inst_A64_is_indirect_branch(uint32_t inst) +int inst_A64_is_indirect_branch(uint32_t inst, struct decode_info *info) { uint8_t link = 0; - return inst_A64_is_indirect_branch_link(inst, &link); + return inst_A64_is_indirect_branch_link(inst, &link, info); } -int inst_A64_is_indirect_branch_link(uint32_t inst, uint8_t *is_link) +int inst_A64_is_indirect_branch_link(uint32_t inst, uint8_t *is_link, struct decode_info *info) { int is_indirect_branch = 1; @@ -301,34 +280,34 @@ int inst_A64_is_indirect_branch_link(uint32_t inst, uint8_t *is_link) /* BR, BLR */ if (inst & 0x00200000) { *is_link = 1; - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; } } else if ((inst & 0xfffffc1f) == 0xd65f0000) { - instr_sub_type = OCSD_S_INSTR_V8_RET; + info->instr_sub_type = OCSD_S_INSTR_V8_RET; /* RET */ } else if ((inst & 0xffffffff) == 0xd69f03e0) { /* ERET */ - instr_sub_type = OCSD_S_INSTR_V8_ERET; - } else if (arch_version >= 0x0803) { + info->instr_sub_type = OCSD_S_INSTR_V8_ERET; + } else if (info->arch_version >= 0x0803) { /* new pointer auth instr for v8.3 arch */ - if ((inst & 0xffdff800) == 0xd61f0800) { + if ((inst & 0xffdff800) == 0xd71f0800) { /* BRAA, BRAB, BLRAA, BLRBB */ if (inst & 0x00200000) { *is_link = 1; - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; } - } else if ((inst & 0xffdff81F) == 0xd71f081F) { + } else if ((inst & 0xffdff81F) == 0xd61f081F) { /* BRAAZ, BRABZ, BLRAAZ, BLRBBZ */ if (inst & 0x00200000) { *is_link = 1; - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; } } else if ((inst & 0xfffffbff) == 0xd69f0bff) { /* ERETAA, ERETAB */ - instr_sub_type = OCSD_S_INSTR_V8_ERET; + info->instr_sub_type = OCSD_S_INSTR_V8_ERET; } else if ((inst & 0xfffffbff) == 0xd65f0bff) { /* RETAA, RETAB */ - instr_sub_type = OCSD_S_INSTR_V8_RET; + info->instr_sub_type = OCSD_S_INSTR_V8_RET; } else { is_indirect_branch = 0; } @@ -441,39 +420,39 @@ int inst_A64_branch_destination(uint64_t addr, uint32_t inst, uint64_t *pnpc) return is_direct_branch; } -int inst_ARM_is_branch(uint32_t inst) +int inst_ARM_is_branch(uint32_t inst, struct decode_info *info) { - return inst_ARM_is_indirect_branch(inst) || + return inst_ARM_is_indirect_branch(inst, info) || inst_ARM_is_direct_branch(inst); } -int inst_Thumb_is_branch(uint32_t inst) +int inst_Thumb_is_branch(uint32_t inst, struct decode_info *info) { - return inst_Thumb_is_indirect_branch(inst) || - inst_Thumb_is_direct_branch(inst); + return inst_Thumb_is_indirect_branch(inst, info) || + inst_Thumb_is_direct_branch(inst, info); } -int inst_A64_is_branch(uint32_t inst) +int inst_A64_is_branch(uint32_t inst, struct decode_info *info) { - return inst_A64_is_indirect_branch(inst) || - inst_A64_is_direct_branch(inst); + return inst_A64_is_indirect_branch(inst, info) || + inst_A64_is_direct_branch(inst, info); } -int inst_ARM_is_branch_and_link(uint32_t inst) +int inst_ARM_is_branch_and_link(uint32_t inst, struct decode_info *info) { int is_branch = 1; if ((inst & 0xf0000000) == 0xf0000000) { if ((inst & 0xfe000000) == 0xfa000000){ - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; /* BLX (imm) */ } else { is_branch = 0; } } else if ((inst & 0x0f000000) == 0x0b000000) { - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; /* BL */ } else if ((inst & 0x0ff000f0) == 0x01200030) { - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; /* BLX (reg) */ } else { is_branch = 0; @@ -481,14 +460,14 @@ int inst_ARM_is_branch_and_link(uint32_t inst) return is_branch; } -int inst_Thumb_is_branch_and_link(uint32_t inst) +int inst_Thumb_is_branch_and_link(uint32_t inst, struct decode_info *info) { int is_branch = 1; if ((inst & 0xff800000) == 0x47800000) { - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; /* BLX (reg) */ } else if ((inst & 0xf800c000) == 0xf000c000) { - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; /* BL, BLX (imm) */ } else { is_branch = 0; @@ -496,23 +475,23 @@ int inst_Thumb_is_branch_and_link(uint32_t inst) return is_branch; } -int inst_A64_is_branch_and_link(uint32_t inst) +int inst_A64_is_branch_and_link(uint32_t inst, struct decode_info *info) { int is_branch = 1; if ((inst & 0xfffffc1f) == 0xd63f0000) { /* BLR */ - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; } else if ((inst & 0xfc000000) == 0x94000000) { /* BL */ - instr_sub_type = OCSD_S_INSTR_BR_LINK; - } else if (arch_version >= 0x0803) { + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; + } else if (info->arch_version >= 0x0803) { /* new pointer auth instr for v8.3 arch */ if ((inst & 0xfffff800) == 0xd73f0800) { /* BLRAA, BLRBB */ - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; } else if ((inst & 0xfffff81F) == 0xd63f081F) { /* BLRAAZ, BLRBBZ */ - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; } else { is_branch = 0; } diff --git a/contrib/opencsd/decoder/source/mem_acc/trc_mem_acc_bufptr.cpp b/contrib/opencsd/decoder/source/mem_acc/trc_mem_acc_bufptr.cpp index 25c736387c0b..7ecd3b018dab 100644 --- a/contrib/opencsd/decoder/source/mem_acc/trc_mem_acc_bufptr.cpp +++ b/contrib/opencsd/decoder/source/mem_acc/trc_mem_acc_bufptr.cpp @@ -37,8 +37,7 @@ TrcMemAccBufPtr::TrcMemAccBufPtr(const ocsd_vaddr_t s_address, const uint8_t *p_buffer, const uint32_t size) : TrcMemAccessorBase(MEMACC_BUFPTR, s_address, s_address+size-1), - m_p_buffer(p_buffer), - m_size(size) + m_p_buffer(p_buffer) { } diff --git a/contrib/opencsd/decoder/source/ocsd_dcd_tree.cpp b/contrib/opencsd/decoder/source/ocsd_dcd_tree.cpp index cf75e569d72a..be15e36e9cb3 100644 --- a/contrib/opencsd/decoder/source/ocsd_dcd_tree.cpp +++ b/contrib/opencsd/decoder/source/ocsd_dcd_tree.cpp @@ -111,6 +111,7 @@ DecodeTree::~DecodeTree() destroyDecodeElement(i); } PktPrinterFact::destroyAllPrinters(m_printer_list); + delete m_frame_deformatter_root; } diff --git a/contrib/opencsd/decoder/source/ocsd_error.cpp b/contrib/opencsd/decoder/source/ocsd_error.cpp index 251964b7a4b0..74e9e4977f60 100644 --- a/contrib/opencsd/decoder/source/ocsd_error.cpp +++ b/contrib/opencsd/decoder/source/ocsd_error.cpp @@ -207,7 +207,7 @@ const std::string ocsdError::getErrorString(const ocsdError &error) void ocsdError::appendErrorDetails(std::string &errStr, const ocsdError &error) { - int numerrstr = ((sizeof(s_errorCodeDescs) / sizeof(const char *)) / 2); + int numerrstr = sizeof(s_errorCodeDescs) / sizeof(s_errorCodeDescs[0]); int code = (int)error.getErrorCode(); ocsd_trc_index_t idx = error.getErrorIndex(); uint8_t chan_ID = error.getErrorChanID(); diff --git a/contrib/opencsd/decoder/source/ocsd_gen_elem_stack.cpp b/contrib/opencsd/decoder/source/ocsd_gen_elem_stack.cpp new file mode 100644 index 000000000000..bb758427a9b8 --- /dev/null +++ b/contrib/opencsd/decoder/source/ocsd_gen_elem_stack.cpp @@ -0,0 +1,196 @@ +/* +* \file ocsd_gen_elem_stack.cpp +* \brief OpenCSD : List of Generic trace elements for output. +* +* \copyright Copyright (c) 2020, 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 "common/ocsd_gen_elem_stack.h" + +OcsdGenElemStack::OcsdGenElemStack() : + m_pElemArray(0), + m_elemArraySize(0), + m_elem_to_send(0), + m_curr_elem_idx(0), + m_send_elem_idx(0), + m_CSID(0), + m_is_init(false) +{ + +} + +OcsdGenElemStack::~OcsdGenElemStack() +{ + for (int i = 0; i 0) + copyPersistentData(m_curr_elem_idx, 0); + + // indexes to bottom of stack, nothing in use at present + m_curr_elem_idx = 0; + m_send_elem_idx = 0; + m_elem_to_send = 0; +} + +ocsd_datapath_resp_t OcsdGenElemStack::sendElements() +{ + ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + if (!isInit()) + return OCSD_RESP_FATAL_NOT_INIT; + + while (m_elem_to_send && OCSD_DATA_RESP_IS_CONT(resp)) + { + resp = m_sendIf->first()->TraceElemIn(m_pElemArray[m_send_elem_idx].trc_pkt_idx, m_CSID, *(m_pElemArray[m_send_elem_idx].pElem)); + m_send_elem_idx++; + m_elem_to_send--; + } + + // clear the indexes if we are done. + if (!m_elem_to_send) + resetIndexes(); + return resp; +} + +ocsd_err_t OcsdGenElemStack::growArray() +{ + elemPtr_t *p_new_array = 0; + const int increment = 4; + + p_new_array = new (std::nothrow) elemPtr_t[m_elemArraySize + increment]; + + if (p_new_array != 0) + { + OcsdTraceElement *pElem = 0; + + // fill the last increment elements with new objects + for (int i = 0; i < increment; i++) + { + pElem = new (std::nothrow) OcsdTraceElement(); + if (!pElem) + return OCSD_ERR_MEM; + pElem->init(); + p_new_array[m_elemArraySize + i].pElem = pElem; + } + + // copy the existing objects from the old array to the start of the new one + if (m_elemArraySize > 0) + { + for (int i = 0; i < m_elemArraySize; i++) + { + p_new_array[i].pElem = m_pElemArray[i].pElem; + p_new_array[i].trc_pkt_idx = m_pElemArray[i].trc_pkt_idx; + } + } + + // delete the old pointer array. + delete[] m_pElemArray; + m_elemArraySize += increment; + m_pElemArray = p_new_array; + } + else + return OCSD_ERR_MEM; + + return OCSD_OK; +} + +void OcsdGenElemStack::copyPersistentData(int src, int dst) +{ + m_pElemArray[dst].pElem->copyPersistentData(*(m_pElemArray[src].pElem)); +} + +const bool OcsdGenElemStack::isInit() +{ + if (!m_is_init) { + if (m_elemArraySize && m_pElemArray && m_sendIf) + m_is_init = true; + } + return m_is_init; +} + + +/* End of File ocsd_gen_elem_stack.cpp */ diff --git a/contrib/opencsd/decoder/source/ptm/trc_pkt_decode_ptm.cpp b/contrib/opencsd/decoder/source/ptm/trc_pkt_decode_ptm.cpp index 94ed5acc243a..7abee8499f46 100644 --- a/contrib/opencsd/decoder/source/ptm/trc_pkt_decode_ptm.cpp +++ b/contrib/opencsd/decoder/source/ptm/trc_pkt_decode_ptm.cpp @@ -67,6 +67,7 @@ ocsd_datapath_resp_t TrcPktDecodePtm::processPacket() case NO_SYNC: // no sync - output a no sync packet then transition to wait sync. m_output_elem.elem_type = OCSD_GEN_TRC_ELEM_NO_SYNC; + m_output_elem.unsync_eot_info = m_unsync_info; resp = outputTraceElement(m_output_elem); m_curr_state = (m_curr_packet_in->getType() == PTM_PKT_A_SYNC) ? WAIT_ISYNC : WAIT_SYNC; bPktDone = true; @@ -108,6 +109,7 @@ ocsd_datapath_resp_t TrcPktDecodePtm::onEOT() // shouldn't be any packets left to be processed - flush shoudl have done this. // just output the end of trace marker m_output_elem.setType(OCSD_GEN_TRC_ELEM_EO_TRACE); + m_output_elem.setUnSyncEOTReason(UNSYNC_EOT); resp = outputTraceElement(m_output_elem); return resp; } @@ -115,6 +117,7 @@ ocsd_datapath_resp_t TrcPktDecodePtm::onEOT() ocsd_datapath_resp_t TrcPktDecodePtm::onReset() { ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + m_unsync_info = UNSYNC_RESET_DECODER; resetDecoder(); return resp; } @@ -191,6 +194,7 @@ void TrcPktDecodePtm::initDecoder() m_instr_info.pe_type.profile = profile_Unknown; m_instr_info.pe_type.arch = ARCH_UNKNOWN; m_instr_info.dsb_dmb_waypoints = 0; + m_unsync_info = UNSYNC_INIT_DECODER; resetDecoder(); } @@ -504,11 +508,15 @@ ocsd_datapath_resp_t TrcPktDecodePtm::processAtomRange(const ocsd_atm_val A, con ocsd_datapath_resp_t resp = OCSD_RESP_CONT; bool bWPFound = false; std::ostringstream oss; + ocsd_err_t err = OCSD_OK; m_instr_info.instr_addr = m_curr_pe_state.instr_addr; m_instr_info.isa = m_curr_pe_state.isa; - ocsd_err_t err = traceInstrToWP(bWPFound,traceWPOp,nextAddrMatch); + // set type (which resets out-elem) before traceInstrToWP modifies out-elem values + m_output_elem.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE); + + err = traceInstrToWP(bWPFound,traceWPOp,nextAddrMatch); if(err != OCSD_OK) { if(err == OCSD_ERR_UNSUPPORTED_ISA) @@ -576,7 +584,6 @@ ocsd_datapath_resp_t TrcPktDecodePtm::processAtomRange(const ocsd_atm_val A, con break; } - m_output_elem.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE); m_output_elem.setLastInstrInfo((A == ATOM_E),m_instr_info.type, m_instr_info.sub_type,m_instr_info.instr_size); m_output_elem.setISA(m_curr_pe_state.isa); if(m_curr_packet_in->hasCC()) @@ -595,7 +602,6 @@ ocsd_datapath_resp_t TrcPktDecodePtm::processAtomRange(const ocsd_atm_val A, con if(m_output_elem.st_addr != m_output_elem.en_addr) { // some trace before we were out of memory access range - m_output_elem.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE); m_output_elem.setLastInstrInfo(true,m_instr_info.type, m_instr_info.sub_type,m_instr_info.instr_size); m_output_elem.setISA(m_curr_pe_state.isa); m_output_elem.setLastInstrCond(m_instr_info.is_conditional); diff --git a/contrib/opencsd/decoder/source/stm/trc_pkt_decode_stm.cpp b/contrib/opencsd/decoder/source/stm/trc_pkt_decode_stm.cpp index a47e96312546..1bb8d7346be0 100644 --- a/contrib/opencsd/decoder/source/stm/trc_pkt_decode_stm.cpp +++ b/contrib/opencsd/decoder/source/stm/trc_pkt_decode_stm.cpp @@ -68,6 +68,7 @@ ocsd_datapath_resp_t TrcPktDecodeStm::processPacket() { case NO_SYNC: m_output_elem.setType(OCSD_GEN_TRC_ELEM_NO_SYNC); + m_output_elem.setUnSyncEOTReason(m_unsync_info); resp = outputTraceElement(m_output_elem); m_curr_state = WAIT_SYNC; break; @@ -90,6 +91,7 @@ ocsd_datapath_resp_t TrcPktDecodeStm::onEOT() { ocsd_datapath_resp_t resp = OCSD_RESP_CONT; m_output_elem.setType(OCSD_GEN_TRC_ELEM_EO_TRACE); + m_output_elem.setUnSyncEOTReason(UNSYNC_EOT); resp = outputTraceElement(m_output_elem); return resp; } @@ -97,6 +99,7 @@ ocsd_datapath_resp_t TrcPktDecodeStm::onEOT() ocsd_datapath_resp_t TrcPktDecodeStm::onReset() { ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + m_unsync_info = UNSYNC_RESET_DECODER; resetDecoder(); return resp; } @@ -127,7 +130,7 @@ void TrcPktDecodeStm::initDecoder() // base decoder state - STM requires no memory and instruction decode. setUsesMemAccess(false); setUsesIDecode(false); - + m_unsync_info = UNSYNC_INIT_DECODER; resetDecoder(); } @@ -166,6 +169,7 @@ ocsd_datapath_resp_t TrcPktDecodeStm::decodePacket(bool &bPktDone) case STM_PKT_BAD_SEQUENCE: /**< Incorrect protocol sequence */ case STM_PKT_RESERVED: resp = OCSD_RESP_FATAL_INVALID_DATA; + m_unsync_info = UNSYNC_BAD_PACKET; case STM_PKT_NOTSYNC: resetDecoder(); break; diff --git a/contrib/opencsd/decoder/source/trc_component.cpp b/contrib/opencsd/decoder/source/trc_component.cpp index 47200a1ead67..dae92d4213de 100644 --- a/contrib/opencsd/decoder/source/trc_component.cpp +++ b/contrib/opencsd/decoder/source/trc_component.cpp @@ -41,7 +41,13 @@ class errLogAttachMonitor : public IComponentAttachNotifier { m_pComp = 0; }; - virtual ~ errLogAttachMonitor() {}; + virtual ~ errLogAttachMonitor() + { + if (m_pComp) + m_pComp->getErrorLogAttachPt()->set_notifier(0); + m_pComp = 0; + + }; virtual void attachNotify(const int num_attached) { if(m_pComp) @@ -73,6 +79,8 @@ TraceComponent::TraceComponent(const std::string &name, int instIDNum) TraceComponent::~TraceComponent() { + if (m_pErrAttachMon) + delete m_pErrAttachMon; } void TraceComponent::Init(const std::string &name) @@ -140,9 +148,7 @@ void TraceComponent::updateErrorLogLevel() ocsd_err_t TraceComponent::setComponentOpMode(uint32_t op_flags) { - if( (~m_supported_op_flags & op_flags) != 0) - return OCSD_ERR_INVALID_PARAM_VAL; - m_op_flags = op_flags; + m_op_flags = op_flags & m_supported_op_flags; return OCSD_OK; } diff --git a/contrib/opencsd/decoder/source/trc_core_arch_map.cpp b/contrib/opencsd/decoder/source/trc_core_arch_map.cpp index 70a25eef0359..a26f79db996e 100644 --- a/contrib/opencsd/decoder/source/trc_core_arch_map.cpp +++ b/contrib/opencsd/decoder/source/trc_core_arch_map.cpp @@ -34,10 +34,12 @@ #include "common/trc_core_arch_map.h" -static struct _ap_map_elements { +typedef struct _ap_map_elements { const char *name; ocsd_arch_profile_t ap; -} ap_map_array[] = +} ap_map_elem_t; + +static ap_map_elem_t ap_map_array[] = { { "Cortex-A77", { ARCH_V8r3, profile_CortexA } }, { "Cortex-A76", { ARCH_V8r3, profile_CortexA } }, @@ -70,12 +72,28 @@ static struct _ap_map_elements { { "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() { - for(unsigned i = 0; i < sizeof(ap_map_array)/sizeof(_ap_map_elements); i++) + unsigned i; + for (i = 0; i < sizeof(ap_map_array) / sizeof(_ap_map_elements); i++) { 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; + } } /* End of File trc_core_arch_map.cpp */ diff --git a/contrib/opencsd/decoder/source/trc_gen_elem.cpp b/contrib/opencsd/decoder/source/trc_gen_elem.cpp index b3ec75f059d4..e1774203ebc5 100644 --- a/contrib/opencsd/decoder/source/trc_gen_elem.cpp +++ b/contrib/opencsd/decoder/source/trc_gen_elem.cpp @@ -46,6 +46,7 @@ static const char *s_elem_descs[][2] = {"OCSD_GEN_TRC_ELEM_EO_TRACE","End of the available trace in the buffer."}, {"OCSD_GEN_TRC_ELEM_PE_CONTEXT","PE status update / change (arch, ctxtid, vmid etc)."}, {"OCSD_GEN_TRC_ELEM_INSTR_RANGE","Traced N consecutive instructions from addr (no intervening events or data elements), may have data assoc key"}, + {"OCSD_GEN_TRC_ELEM_I_RANGE_NOPATH","Traced N instructions in a range, but incomplete information as to program execution path from start to end of range"}, {"OCSD_GEN_TRC_ELEM_ADDR_NACC","Tracing in inaccessible memory area."}, {"OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN","Tracing unknown address area."}, {"OCSD_GEN_TRC_ELEM_EXCEPTION","Exception"}, @@ -62,7 +63,8 @@ static const char *instr_type[] = { "BR ", "iBR ", "ISB ", - "DSB.DMB" + "DSB.DMB", + "WFI.WFE" }; #define T_SIZE (sizeof(instr_type) / sizeof(const char *)) @@ -94,10 +96,20 @@ static const char *s_isa_str[] = { "Unk" /**< ISA not yet known */ }; +static const char *s_unsync_reason[] = { + "undefined", // UNSYNC_UNKNOWN - unknown /undefined + "init-decoder", // UNSYNC_INIT_DECODER - decoder intialisation - start of trace. + "reset-decoder", // UNSYNC_RESET_DECODER - decoder reset. + "overflow", // UNSYNC_OVERFLOW - overflow packet - need to re-sync + "discard", // UNSYNC_DISCARD - specl trace discard - need to re-sync + "bad-packet", // UNSYNC_BAD_PACKET - bad packet at input - resync to restart. + "end-of-trace", // UNSYNC_EOT - end of trace info. +}; + void OcsdTraceElement::toString(std::string &str) const { std::ostringstream oss; - int num_str = ((sizeof(s_elem_descs) / sizeof(const char *)) / 2); + int num_str = sizeof(s_elem_descs) / sizeof(s_elem_descs[0]); int typeIdx = (int)this->elem_type; if(typeIdx < num_str) { @@ -122,6 +134,11 @@ void OcsdTraceElement::toString(std::string &str) const oss << " 0x" << std::hex << st_addr << " "; break; + case OCSD_GEN_TRC_ELEM_I_RANGE_NOPATH: + oss << "first 0x" << std::hex << st_addr << ":[next 0x" << en_addr << "] "; + oss << "num_i(" << std::dec << num_instr_range << ") "; + break; + case OCSD_GEN_TRC_ELEM_EXCEPTION: if (excep_ret_addr == 1) { @@ -167,6 +184,12 @@ void OcsdTraceElement::toString(std::string &str) const oss << " Numbered:" << std::dec << trace_event.ev_number << "; "; break; + case OCSD_GEN_TRC_ELEM_EO_TRACE: + case OCSD_GEN_TRC_ELEM_NO_SYNC: + if (unsync_eot_info <= UNSYNC_EOT) + oss << " [" << s_unsync_reason[unsync_eot_info] << "]"; + break; + default: break; } if(has_cc) diff --git a/lib/libopencsd/Makefile b/lib/libopencsd/Makefile index 9da200aad3fc..f28b14977cfa 100644 --- a/lib/libopencsd/Makefile +++ b/lib/libopencsd/Makefile @@ -40,10 +40,8 @@ SRCS+= \ trc_cmp_cfg_etmv4.cpp \ trc_etmv4_stack_elem.cpp \ trc_pkt_decode_etmv4i.cpp \ - trc_pkt_elem_etmv4d.cpp \ trc_pkt_elem_etmv4i.cpp \ - trc_pkt_proc_etmv4.cpp \ - trc_pkt_proc_etmv4i_impl.cpp + trc_pkt_proc_etmv4i.cpp # PKT_PRINTERS SRCS+= \ @@ -75,6 +73,7 @@ SRCS+= \ ocsd_error.cpp \ ocsd_error_logger.cpp \ ocsd_gen_elem_list.cpp \ + ocsd_gen_elem_stack.cpp \ ocsd_lib_dcd_register.cpp \ ocsd_msg_logger.cpp \ ocsd_version.cpp \ @@ -126,9 +125,9 @@ ETMV4INCS= \ trc_dcd_mngr_etmv4i.h \ trc_etmv4_stack_elem.h \ trc_pkt_decode_etmv4i.h \ - trc_pkt_elem_etmv4d.h \ trc_pkt_elem_etmv4i.h \ trc_pkt_proc_etmv4.h \ + trc_pkt_proc_etmv4i.h \ trc_pkt_types_etmv4.h ETMV4INCSDIR=${INCLUDEDIR}/opencsd/etmv4/