Full decoder now complete.
Tested against TC2 snapshot. C-API updated and test program run to check consistency
Signed-off-by: Mike Leach mike.leach@linaro.org --- .../ref_trace_decode_lib.vcxproj | 2 + .../ref_trace_decode_lib.vcxproj.filters | 6 + decoder/include/c_api/opencsd_c_api.h | 13 + decoder/include/common/ocsd_code_follower.h | 6 + decoder/include/common/ocsd_dcd_tree_elem.h | 4 +- decoder/include/common/ocsd_gen_elem_list.h | 153 +++++ decoder/include/common/ocsd_pe_context.h | 22 + decoder/include/common/trc_gen_elem.h | 80 ++- decoder/include/etmv3/trc_cmp_cfg_etmv3.h | 10 + decoder/include/etmv3/trc_pkt_decode_etmv3.h | 167 +++++- decoder/include/etmv3/trc_pkt_elem_etmv3.h | 24 +- decoder/include/etmv3/trc_pkt_types_etmv3.h | 12 +- decoder/include/ocsd_if_types.h | 4 +- decoder/include/trc_gen_elem_types.h | 3 +- decoder/include/trc_pkt_types.h | 2 +- decoder/source/c_api/ocsd_c_api.cpp | 17 + decoder/source/etmv3/trc_pkt_decode_etmv3.cpp | 619 ++++++++++++++++----- decoder/source/ocsd_code_follower.cpp | 3 +- decoder/source/ocsd_dcd_tree.cpp | 29 +- decoder/source/ocsd_error.cpp | 3 +- decoder/source/ocsd_gen_elem_list.cpp | 168 ++++++ decoder/source/trc_gen_elem.cpp | 19 +- decoder/tests/source/simple_pkt_c_api.c | 18 +- 23 files changed, 1179 insertions(+), 205 deletions(-) create mode 100644 decoder/include/common/ocsd_gen_elem_list.h create mode 100644 decoder/source/ocsd_gen_elem_list.cpp
diff --git a/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj b/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj index 2dc5f0c..929df5a 100644 --- a/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj +++ b/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj @@ -309,6 +309,7 @@ <ClInclude Include="..\..\..\include\common\ocsd_dcd_tree_elem.h" /> <ClInclude Include="..\..\..\include\common\ocsd_error.h" /> <ClInclude Include="..\..\..\include\common\ocsd_error_logger.h" /> + <ClInclude Include="..\..\..\include\common\ocsd_gen_elem_list.h" /> <ClInclude Include="..\..\..\include\common\ocsd_msg_logger.h" /> <ClInclude Include="..\..\..\include\common\ocsd_pe_context.h" /> <ClInclude Include="..\..\..\include\common\ocsd_version.h" /> @@ -395,6 +396,7 @@ <ClCompile Include="..\..\..\source\ocsd_dcd_tree.cpp" /> <ClCompile Include="..\..\..\source\ocsd_error.cpp" /> <ClCompile Include="..\..\..\source\ocsd_error_logger.cpp" /> + <ClCompile Include="..\..\..\source\ocsd_gen_elem_list.cpp" /> <ClCompile Include="..\..\..\source\ocsd_msg_logger.cpp" /> <ClCompile Include="..\..\..\source\ocsd_version.cpp" /> <ClCompile Include="..\..\..\source\ptm\trc_cmp_cfg_ptm.cpp" /> diff --git a/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj.filters b/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj.filters index c221d2f..efb3183 100644 --- a/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj.filters +++ b/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj.filters @@ -287,6 +287,9 @@ <ClInclude Include="..\..\..\include\common\ocsd_code_follower.h"> <Filter>Header Files\common</Filter> </ClInclude> + <ClInclude Include="..\..\..\include\common\ocsd_gen_elem_list.h"> + <Filter>Header Files\common</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="..\..\..\source\trc_component.cpp"> @@ -394,5 +397,8 @@ <ClCompile Include="..\..\..\source\ocsd_code_follower.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="..\..\..\source\ocsd_gen_elem_list.cpp"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> </Project> \ No newline at end of file diff --git a/decoder/include/c_api/opencsd_c_api.h b/decoder/include/c_api/opencsd_c_api.h index 480969c..5574f19 100644 --- a/decoder/include/c_api/opencsd_c_api.h +++ b/decoder/include/c_api/opencsd_c_api.h @@ -207,6 +207,19 @@ OCSD_C_API ocsd_err_t ocsd_dt_create_etmv3_pkt_proc(const dcd_tree_handle_t hand
/*! + * Creates a packet processor + packet decoder pair for the supplied configuration structure. + * Uses the output function set in ocsd_dt_set_gen_elem_outfn() as the output sink. + * + * @param handle : Handle to decode tree. + * @param *etmv4_cfg : pointer to valid Etmv4 configuration structure. + * + * @return ocsd_err_t : Library error code - RCDTL_OK if successful. + */ +OCSD_C_API ocsd_err_t ocsd_dt_create_etmv3_decoder(const dcd_tree_handle_t handle, const void *etmv3_cfg); + + + +/*! * Attach a callback function to the packet processor monitor point defined by the CoreSight ID. * Packet processor must exist for the trace ID and be an ETMv3 processor. * diff --git a/decoder/include/common/ocsd_code_follower.h b/decoder/include/common/ocsd_code_follower.h index e8df24a..7063266 100644 --- a/decoder/include/common/ocsd_code_follower.h +++ b/decoder/include/common/ocsd_code_follower.h @@ -83,6 +83,7 @@ public: //*********************** results API const ocsd_vaddr_t getRangeSt() const; //!< inclusive start address of decoded range (value passed in) const ocsd_vaddr_t getRangeEn() const; //!< exclusive end address of decoded range (first instruction _not_ executed / potential next instruction). + const bool hasRange() const; //!< we have a valid range executed (may be false if nacc).
const bool hasNextAddr() const; //!< we have calulated the next address - otherwise this is needed from trace packets. const ocsd_vaddr_t getNextAddr() const; //!< next address - valid if hasNextAddr() true. @@ -165,6 +166,11 @@ inline const ocsd_vaddr_t OcsdCodeFollower::getRangeEn() const return m_en_range_addr; }
+inline const bool OcsdCodeFollower::hasRange() const +{ + return m_st_range_addr < m_en_range_addr; +} + inline const bool OcsdCodeFollower::hasNextAddr() const { return m_b_next_valid; diff --git a/decoder/include/common/ocsd_dcd_tree_elem.h b/decoder/include/common/ocsd_dcd_tree_elem.h index b1b14d0..31fe011 100644 --- a/decoder/include/common/ocsd_dcd_tree_elem.h +++ b/decoder/include/common/ocsd_dcd_tree_elem.h @@ -49,7 +49,7 @@ typedef struct _decoder_elements union { struct { TrcPktProcEtmV3 *proc; - void * /*TrcPktDecodeEtmV3 * */ dcd; //** TBD + TrcPktDecodeEtmV3 *dcd; } etmv3; /**< ETMv3 decoders */ struct { TrcPktProcEtmV4I *proc; @@ -155,7 +155,7 @@ public: switch(protocol) { case OCSD_PROTOCOL_ETMV3: - //pDecoder = dynamic_cast<TrcPktDecodeI *>(decoder.etmv3.dcd); + pDecoder = dynamic_cast<TrcPktDecodeI *>(decoder.etmv3.dcd); break; case OCSD_PROTOCOL_ETMV4I: pDecoder = dynamic_cast<TrcPktDecodeI *>(decoder.etmv4i.dcd); diff --git a/decoder/include/common/ocsd_gen_elem_list.h b/decoder/include/common/ocsd_gen_elem_list.h new file mode 100644 index 0000000..0ff1bd5 --- /dev/null +++ b/decoder/include/common/ocsd_gen_elem_list.h @@ -0,0 +1,153 @@ +/* + * \file ocsd_gen_elem_stack.h + * \brief OpenCSD : Generic element output stack. + * + * \copyright Copyright (c) 2016, 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 <list> +#include "trc_gen_elem.h" +#include "comp_attach_pt_t.h" +#include "interfaces/trc_gen_elem_in_i.h" + +/*! + * @class OcsdGenElemList + * @brief Maintain a list of elements to be output + * + * Each incoming packet can result in multiple output elements. + * These are stacked in this class prior to entering the output phase of processing. + * + * 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. + * (This required for cancel element in ETMv3 exeception branch). + * + * The "list" is actually a ring buffer - maintaining pointers to indicate current valid elements. + * This buffer can increase on demand, but will only be released at the end of a decode session. + */ +class OcsdGenElemList +{ +public: + OcsdGenElemList(); + ~OcsdGenElemList(); + + void initSendIf(componentAttachPt<ITrcGenElemIn> *pGenElemIf); + void initCSID(const uint8_t CSID) { m_CSID = CSID; }; + + void reset(); //!< reset the element list. + + OcsdTraceElement *getNextElem(const ocsd_trc_index_t trc_pkt_idx); //!< get next free element on the stack (add one to the output) + const int getNumElem() const; //!< return the total number of elements on the stack (inlcuding any pended ones). + + const ocsd_gen_trc_elem_t getElemType(const int entryN) const; //!< get the type for the nth element in the stack (0 indexed) + + void pendLastNElem(int numPend); //!< Last element to be pended prior to cancel/commit decision. + void commitAllPendElem(); //!< commit all pended elements. + void cancelPendElem(); //!< cancel the last pended element on the stack. + const int numPendElem() const; //!< return the number of pended elements. + + /*! Send all of the none pended elements + Stop sending when all sent or _CONT response. + */ + ocsd_datapath_resp_t sendElements(); + const bool elemToSend() const; //!< true if any none-pending elements left to send. + +private: + + void growArray(); + const int getAdjustedIdx(int idxIn) const; //!< get adjusted index into circular buffer. + + + // list element contains pointer and byte index in trace stream + 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; + + elemPtr_t *m_pElemArray; //!< an array of pointers to elements. + int m_elemArraySize; //!< number of element pointers in the array + + int m_firstElemIdx; //!< internal index in array of first element in use. + int m_numUsed; //!< number of elements in use + int m_numPend; //!< internal count of pended elements. + + uint8_t m_CSID; + + componentAttachPt<ITrcGenElemIn> *m_sendIf; //!< element send interface. +}; + +inline const int OcsdGenElemList::getAdjustedIdx(int idxIn) const +{ + if(idxIn >= m_elemArraySize) + idxIn -= m_elemArraySize; + return idxIn; +} + +inline const int OcsdGenElemList::getNumElem() const +{ + return m_numUsed; +} + +inline const int OcsdGenElemList::numPendElem() const +{ + return m_numPend; +} + +inline void OcsdGenElemList::pendLastNElem(int numPend) +{ + if(numPend >= getNumElem()) + m_numPend = numPend; +} + +inline void OcsdGenElemList::commitAllPendElem() +{ + m_numPend = 0; +} + +inline void OcsdGenElemList::cancelPendElem() +{ + if(m_numPend > 0) + { + m_numUsed -= m_numPend; + } +} + +inline const bool OcsdGenElemList::elemToSend() const +{ + return ((getNumElem() - m_numPend) > 0); +} + +inline void OcsdGenElemList::initSendIf(componentAttachPt<ITrcGenElemIn> *pGenElemIf) +{ + m_sendIf = pGenElemIf; +} + +/* End of File ocsd_gen_elem_stack.h */ diff --git a/decoder/include/common/ocsd_pe_context.h b/decoder/include/common/ocsd_pe_context.h index fe06e90..1ad4676 100644 --- a/decoder/include/common/ocsd_pe_context.h +++ b/decoder/include/common/ocsd_pe_context.h @@ -46,8 +46,12 @@ class OcsdPeContext { public: OcsdPeContext(); + OcsdPeContext(const ocsd_pe_context *context); ~OcsdPeContext() {};
+ OcsdPeContext &operator =(const OcsdPeContext &ctxt); + OcsdPeContext &operator =(const ocsd_pe_context *context); + void resetCtxt();
void setSecLevel(const ocsd_sec_level sl) { m_context.security_level = sl; }; @@ -76,6 +80,11 @@ inline OcsdPeContext::OcsdPeContext() resetCtxt(); }
+inline OcsdPeContext::OcsdPeContext(const ocsd_pe_context *context) +{ + m_context = *context; +} + inline void OcsdPeContext::resetCtxt() { // initialise the context @@ -89,6 +98,19 @@ inline void OcsdPeContext::resetCtxt() m_context.vmid_valid = 0; }
+inline OcsdPeContext & OcsdPeContext::operator =(const OcsdPeContext &ctxt) +{ + m_context = ctxt; + return *this; +} + +inline OcsdPeContext & OcsdPeContext::operator =(const ocsd_pe_context *context) +{ + m_context = *context; + return *this; +} + + #endif // ARM_OCSD_PE_CONTEXT_H_INCLUDED
/* End of File ocsd_pe_context.h */ diff --git a/decoder/include/common/trc_gen_elem.h b/decoder/include/common/trc_gen_elem.h index d5fbe41..4f99c378 100644 --- a/decoder/include/common/trc_gen_elem.h +++ b/decoder/include/common/trc_gen_elem.h @@ -36,6 +36,8 @@
#include "trc_gen_elem_types.h" #include "trc_printable_elem.h" +#include "ocsd_pe_context.h" + /** @addtogroup gen_trc_elem @{*/
@@ -53,18 +55,47 @@ public:
void init();
- const ocsd_gen_trc_elem_t getType() const { return elem_type; }; - void setType(const ocsd_gen_trc_elem_t type); +// set elements API + + void setType(const ocsd_gen_trc_elem_t type); //!< set type and init flags + void updateType(const ocsd_gen_trc_elem_t type); //!< change type only - no init + void setContext(const ocsd_pe_context &new_context) { context = new_context; }; + void setISA(const ocsd_isa isa_update); + void setCycleCount(const uint32_t cycleCount); void setEvent(const event_t ev_type, const uint16_t number); void setTS(const uint64_t ts, const bool freqChange = false) { timestamp = ts; cpu_freq_change = freqChange ? 1 : 0; }; + void setExcepMarker() { excep_data_marker = 1; }; + void setExceptionNum(uint32_t excepNum) { exception_number = excepNum; }; + + + void setTraceOnReason(const trace_on_reason_t reason); + + void setAddrRange(const ocsd_vaddr_t st_addr, const ocsd_vaddr_t en_addr); + void setLastInstrInfo(const bool exec, const ocsd_instr_type last_i_type, const ocsd_instr_subtype last_i_subtype); + void setAddrStart(const ocsd_vaddr_t st_addr) { this->st_addr = st_addr; }; + + + +// stringize the element
virtual void toString(std::string &str) const;
+// get elements API + OcsdTraceElement &operator =(const ocsd_generic_trace_elem* p_elem);
+ const ocsd_gen_trc_elem_t getType() const { return elem_type; }; + + // return current context + const ocsd_pe_context &getContext() const { return context; }; + + +private: + void clearPerPktData(); //!< clear flags that indicate validity / have values on a per packet basis + };
inline OcsdTraceElement::OcsdTraceElement(ocsd_gen_trc_elem_t type) @@ -89,16 +120,30 @@ inline void OcsdTraceElement::setEvent(const event_t ev_type, const uint16_t num trace_event.ev_number = ev_type == EVENT_NUMBERED ? number : 0; }
+inline void OcsdTraceElement::setAddrRange(const ocsd_vaddr_t st_addr, const ocsd_vaddr_t en_addr) +{ + this->st_addr = st_addr; + this->en_addr = en_addr; +} + +inline void OcsdTraceElement::setLastInstrInfo(const bool exec, const ocsd_instr_type last_i_type, const ocsd_instr_subtype last_i_subtype) +{ + last_instr_exec = exec ? 1 : 0; + this->last_i_type = last_i_type; + this->last_i_subtype = last_i_subtype; +} + inline void OcsdTraceElement::setType(const ocsd_gen_trc_elem_t type) { // set the type and clear down the per element flags elem_type = type; - has_cc = 0; - last_instr_exec = 0; - last_i_type = OCSD_INSTR_OTHER; - excep_ret_addr = 0; - exception_number = 0; - excep_data_marker = 0; + + clearPerPktData(); +} + +inline void OcsdTraceElement::updateType(const ocsd_gen_trc_elem_t type) +{ + elem_type = type; }
inline void OcsdTraceElement::init() @@ -107,13 +152,32 @@ inline void OcsdTraceElement::init() context.vmid_valid = 0; context.el_valid = 0;
+ last_i_type = OCSD_INSTR_OTHER; + last_i_subtype = OCSD_S_INSTR_NONE; + + clearPerPktData(); +} + +inline void OcsdTraceElement::clearPerPktData() +{ cpu_freq_change = 0; has_cc = 0; last_instr_exec = 0; excep_ret_addr = 0; + exception_number = 0; // union with trace_on_reason / trace_event excep_data_marker = 0; }
+inline void OcsdTraceElement::setTraceOnReason(const trace_on_reason_t reason) +{ + trace_on_reason = reason; +} + +inline void OcsdTraceElement::setISA(const ocsd_isa isa_update) +{ + isa = isa_update; +} + /** @}*/
#endif // ARM_TRC_GEN_ELEM_H_INCLUDED diff --git a/decoder/include/etmv3/trc_cmp_cfg_etmv3.h b/decoder/include/etmv3/trc_cmp_cfg_etmv3.h index a169375..f2da178 100644 --- a/decoder/include/etmv3/trc_cmp_cfg_etmv3.h +++ b/decoder/include/etmv3/trc_cmp_cfg_etmv3.h @@ -214,6 +214,16 @@ inline const uint8_t EtmV3Config::getTraceID() const return (uint8_t)(m_cfg.reg_trc_id & 0x7F); }
+inline const ocsd_arch_version_t EtmV3Config::getArchVersion() const +{ + return m_cfg.arch_ver; +} + +inline const ocsd_core_profile_t EtmV3Config::getCoreProfile() const +{ + return m_cfg.core_prof; +} + /** @}*/
/** @}*/ diff --git a/decoder/include/etmv3/trc_pkt_decode_etmv3.h b/decoder/include/etmv3/trc_pkt_decode_etmv3.h index 5dd78e4..c8487ec 100644 --- a/decoder/include/etmv3/trc_pkt_decode_etmv3.h +++ b/decoder/include/etmv3/trc_pkt_decode_etmv3.h @@ -39,11 +39,151 @@ #include "common/trc_gen_elem.h" #include "common/ocsd_pe_context.h" #include "common/ocsd_code_follower.h" +#include "common/ocsd_gen_elem_list.h"
#include "etmv3/trc_pkt_elem_etmv3.h" #include "etmv3/trc_cmp_cfg_etmv3.h"
+/**************** Atom handling class **************************************/ +class Etmv3Atoms +{ +public: + Etmv3Atoms(const bool isCycleAcc); + ~Etmv3Atoms() {}; + + //! initialise the atom and index values + void initAtomPkt(const EtmV3TrcPacket *in_pkt, const ocsd_trc_index_t &root_index); + + const ocsd_atm_val getCurrAtomVal() const; + const int numAtoms() const; //!< number of atoms + const ocsd_trc_index_t pktIndex() const; //!< originating packet index + + const bool hasAtomCC() const; //!< cycle count for current atom? + const uint32_t getAtomCC() const; //!< cycle count for current atom + const uint32_t getRemainCC() const; //!< get residual cycle count for remaining atoms + + void clearAtom(); //!< clear the current atom, set the next. + void clearAll(); //!< clear all + +private: + ocsd_pkt_atom m_atom; /**< atom elements - non zero number indicates valid atom count */ + uint8_t m_p_hdr_fmt; /**< if atom elements, associated phdr format */ + uint32_t m_cycle_count; + ocsd_trc_index_t m_root_index; //!< root index for the atom packet + bool m_isCCPacket; +}; + +inline Etmv3Atoms::Etmv3Atoms(const bool isCycleAcc) +{ + m_isCCPacket = isCycleAcc; +} + +//! initialise the atom and index values +inline void Etmv3Atoms::initAtomPkt(const EtmV3TrcPacket *in_pkt, const ocsd_trc_index_t &root_index) +{ + m_atom = in_pkt->getAtom(); + m_p_hdr_fmt = in_pkt->getPHdrFmt(); + m_cycle_count = in_pkt->getCycleCount(); +} + +inline const ocsd_atm_val Etmv3Atoms::getCurrAtomVal() const +{ + return (m_atom.En_bits & 0x1) ? ATOM_E : ATOM_N; +}
+inline const int Etmv3Atoms::numAtoms() const +{ + return m_atom.num; +} + +inline const ocsd_trc_index_t Etmv3Atoms::pktIndex() const +{ + return m_root_index; +} + +inline const bool Etmv3Atoms::hasAtomCC() const +{ + bool hasCC = false; + if(m_isCCPacket) + { + switch(m_p_hdr_fmt) + { + case 4: + default: + break; + + case 3: + case 1: + hasCC = true; + break; + + case 2: + hasCC = (m_atom.num > 1); // first of 2 has W state + break; + } + } + return hasCC; +} + +inline const uint32_t Etmv3Atoms::getAtomCC() const +{ + uint32_t CC = 0; + if(m_isCCPacket) + { + switch(m_p_hdr_fmt) + { + case 4: // no CC in format 4 + default: break; + + case 3: // single CC with optional E atom + CC = m_cycle_count; break; + + case 2: // single W on first of 2 atoms + CC = (m_atom.num > 1) ? 1: 0; break; + + case 1: // each atom has 1 CC. + CC = 1; break; + } + } + return CC; +} + +inline const uint32_t Etmv3Atoms::getRemainCC() const +{ + uint32_t CC = 0; + if(m_isCCPacket) + { + switch(m_p_hdr_fmt) + { + case 4: // no CC in format 4 + default: break; + + case 3: + CC = m_cycle_count; break; + + case 2: + CC = (m_atom.num > 1) ? 1: 0; break; + + case 1: + CC = m_atom.num; break; + } + } + return CC; +} + +inline void Etmv3Atoms::clearAtom() +{ + m_atom.En_bits >>=1; + if(m_atom.num) + m_atom.num--; +} + +inline void Etmv3Atoms::clearAll() +{ + m_atom.num = 0; +} + +/********** Main decode class ****************************************************/ class TrcPktDecodeEtmV3 : public TrcPktDecodeBase<EtmV3TrcPacket, EtmV3Config> { public: @@ -64,24 +204,33 @@ protected: void initDecoder(); //!< initial state on creation (zeros all config) void resetDecoder(); //!< reset state to start of decode. (moves state, retains config)
- ocsd_datapath_resp_t decodePacket(); //!< decode a packet + ocsd_datapath_resp_t decodePacket(bool &pktDone); //!< decode a packet
- ocsd_datapath_resp_t processISync(const bool withCC); + ocsd_datapath_resp_t processISync(const bool withCC, const bool firstSync = false); ocsd_datapath_resp_t processBranchAddr(); ocsd_datapath_resp_t processPHdr();
- void pendPacket(); //!< save current packet for re-assess next pass + ocsd_datapath_resp_t sendUnsyncPacket(); //!< send an initial unsync packet when decoder starts + + OcsdTraceElement *GetNextOpElem(ocsd_datapath_resp_t &resp); //!< get the next element from the element list.
private: - + void setNeedAddr(bool bNeedAddr); + void pendExceptionReturn(); + bool preISyncValid(ocsd_etmv3_pkt_type pkt_type); //** intra packet state;
OcsdCodeFollower m_code_follower; //!< code follower for instruction trace
ocsd_vaddr_t m_IAddr; //!< next instruction address - OcsdPeContext m_pe_context; //!< context for the PE + bool m_bNeedAddr; //!< true if an address is needed (current out of date / invalid) + bool m_bSentUnknown; //!< true if we have sent an unknown address packet for this phase of needing an address. + bool m_bWaitISync; //!< true if waiting for first ISync packet + + OcsdPeContext m_PeContext; //!< save context data before sending in output packet + + OcsdGenElemList m_outputElemList; //!< list of output elements
- EtmV3TrcPacket m_pended_packet; //! Saved packet when processing pended.
//** Other packet decoder state;
@@ -91,16 +240,12 @@ private: WAIT_ASYNC, //!< waiting for a-sync packet. WAIT_ISYNC, //!< waiting for i-sync packet. DECODE_PKTS, //!< processing a packet - PEND_INSTR, //!< instruction output pended - need to check next packet for cancel - data in output element - PEND_PACKET, //!< packet decode pended - save previous none decoded packet data - prev pended instr had wait response. + SEND_PKTS, //!< sending packets. } processor_state_t;
processor_state_t m_curr_state;
uint8_t m_CSID; //!< Coresight trace ID for this decoder. - -//** output element - OcsdTraceElement m_output_elem; };
diff --git a/decoder/include/etmv3/trc_pkt_elem_etmv3.h b/decoder/include/etmv3/trc_pkt_elem_etmv3.h index 6e70ade..68438f9 100644 --- a/decoder/include/etmv3/trc_pkt_elem_etmv3.h +++ b/decoder/include/etmv3/trc_pkt_elem_etmv3.h @@ -62,7 +62,7 @@ public: operator const ocsd_etmv3_pkt*() const { return &m_pkt_data; }; operator const ocsd_etmv3_pkt&() const { return m_pkt_data; };
-// update interace - set packet values +// update interface - set packet values void Clear(); //!< clear update data in packet ready for new one. void ResetState(); //!< reset intra packet state data -on full decoder reset.
@@ -103,6 +103,9 @@ public: const ocsd_isa ISA() const { return m_pkt_data.curr_isa; }; const bool changedISA() const { return m_pkt_data.curr_isa != m_pkt_data.prev_isa; };
+ // any of the context elements updated? + const bool isCtxtUpdated() const; + const bool isCtxtFlagsUpdated() const { return (m_pkt_data.context.updated == 1); }; const bool isNS() const { return m_pkt_data.context.curr_NS; }; const bool isHyp() const { return m_pkt_data.context.curr_Hyp; };
@@ -119,6 +122,18 @@ public: const uint16_t excepNum() const { return m_pkt_data.exception.number; }; const bool isExcepCancel() const { return (m_pkt_data.exception.bits.present == 1) && (m_pkt_data.exception.bits.cancel == 1); };
+ const ocsd_iSync_reason getISyncReason() const { return m_pkt_data.isync_info.reason; }; + const bool getISyncHasCC() const { return m_pkt_data.isync_info.has_cycle_count; }; + const bool getISyncIsLSiPAddr() const { return m_pkt_data.isync_info.has_LSipAddress; }; + const bool getISyncNoAddr() const { return m_pkt_data.isync_info.no_address; }; + + const ocsd_vaddr_t getAddr() const { return m_pkt_data.addr.val; }; + const ocsd_vaddr_t getDataAddr() const { return m_pkt_data.data.addr.val; }; + + const ocsd_pkt_atom &getAtom() const { return m_pkt_data.atom; }; + const uint8_t getPHdrFmt() const { return m_pkt_data.p_hdr_fmt; }; + + // printing virtual void toString(std::string &str) const; virtual void toStringFmt(const uint32_t fmtFlags, std::string &str) const; @@ -228,6 +243,13 @@ inline void EtmV3TrcPacket::SetISyncNoAddr() m_pkt_data.isync_info.no_address = 1; }
+inline const bool EtmV3TrcPacket::isCtxtUpdated() const +{ + return (m_pkt_data.context.updated_v == 1) || + (m_pkt_data.context.updated == 1) || + (m_pkt_data.context.updated_c == 1); +} + /** @}*/ #endif // ARM_TRC_PKT_ELEM_ETMV3_H_INCLUDED
diff --git a/decoder/include/etmv3/trc_pkt_types_etmv3.h b/decoder/include/etmv3/trc_pkt_types_etmv3.h index 9a615e5..0be9d98 100644 --- a/decoder/include/etmv3/trc_pkt_types_etmv3.h +++ b/decoder/include/etmv3/trc_pkt_types_etmv3.h @@ -138,14 +138,14 @@ typedef struct _ocsd_etmv3_pkt ocsd_isa curr_isa; /**< current ISA */ ocsd_isa prev_isa; /**< ISA in previous packet */
- etmv3_context_t context; /**< current context */ + etmv3_context_t context; /**< current context */ ocsd_pkt_vaddr addr; /**< current Addr */
etmv3_isync_t isync_info;
ocsd_etmv3_excep exception;
- ocsd_pkt_atom atom; /**< atom elements - non zerom number indicates valid atom count */ + ocsd_pkt_atom atom; /**< atom elements - non zerom number indicates valid atom count */ uint8_t p_hdr_fmt; /**< if atom elements, associated phdr format */ uint32_t cycle_count; /**< cycle count associated with this packet (ETMv3 has counts in atom packets and as individual packets */
@@ -160,10 +160,10 @@ typedef struct _ocsd_etmv3_pkt
typedef struct _ocsd_etmv3_cfg { - uint32_t reg_idr; /**< ID register */ - uint32_t reg_ctrl; /**< Control Register */ - uint32_t reg_ccer; /**< CCER register */ - uint32_t reg_trc_id; /**< Trace Stream ID register */ + uint32_t reg_idr; /**< ID register */ + uint32_t reg_ctrl; /**< Control Register */ + uint32_t reg_ccer; /**< CCER register */ + uint32_t reg_trc_id; /**< Trace Stream ID register */ ocsd_arch_version_t arch_ver; /**< Architecture version */ ocsd_core_profile_t core_prof; /**< Core Profile */ } ocsd_etmv3_cfg; diff --git a/decoder/include/ocsd_if_types.h b/decoder/include/ocsd_if_types.h index 9e4b051..00f8604 100644 --- a/decoder/include/ocsd_if_types.h +++ b/decoder/include/ocsd_if_types.h @@ -48,8 +48,8 @@ /** @name Library Versioning @{*/ #define OCSD_VER_MAJOR 0x0 /**< Library Major Version */ -#define OCSD_VER_MINOR 0x2 /**< Library Minor Version */ -#define OCSD_VER_STRING "0.002" /**< Library Version string */ +#define OCSD_VER_MINOR 0x3 /**< Library Minor Version */ +#define OCSD_VER_STRING "0.003" /**< 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/decoder/include/trc_gen_elem_types.h b/decoder/include/trc_gen_elem_types.h index e0714c0..a274eb8 100644 --- a/decoder/include/trc_gen_elem_types.h +++ b/decoder/include/trc_gen_elem_types.h @@ -53,7 +53,8 @@ typedef enum _ocsd_gen_trc_elem_t 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_ADDR_NACC, /*!< tracing in inaccessible memory area */ - OCSD_GEN_TRC_ELEM_EXCEPTION, /*!< exception - trace range executed up to an exception occurring */ + 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. */ OCSD_GEN_TRC_ELEM_EXCEPTION_RET, /*!< expection return */ OCSD_GEN_TRC_ELEM_TIMESTAMP, /*!< Timestamp - preceding elements happeded before this time. */ OCSD_GEN_TRC_ELEM_CYCLE_COUNT, /*!< Cycle count - cycles since last cycle count value - associated with a preceding instruction range. */ diff --git a/decoder/include/trc_pkt_types.h b/decoder/include/trc_pkt_types.h index 01e3f48..f705875 100644 --- a/decoder/include/trc_pkt_types.h +++ b/decoder/include/trc_pkt_types.h @@ -93,7 +93,7 @@ typedef struct _ocsd_pkt_atom
/** Isync Reason - common to PTM and ETMv3 **/ typedef enum _ocsd_iSync_reason { - iSync_Periodic, + iSync_Periodic = 0, iSync_TraceEnable, iSync_TraceRestartAfterOverflow, iSync_DebugExit diff --git a/decoder/source/c_api/ocsd_c_api.cpp b/decoder/source/c_api/ocsd_c_api.cpp index 1dae2d3..c1d8215 100644 --- a/decoder/source/c_api/ocsd_c_api.cpp +++ b/decoder/source/c_api/ocsd_c_api.cpp @@ -249,6 +249,23 @@ OCSD_C_API ocsd_err_t ocsd_dt_create_etmv3_pkt_proc(const dcd_tree_handle_t hand return err; }
+OCSD_C_API ocsd_err_t ocsd_dt_create_etmv3_decoder(const dcd_tree_handle_t handle, const void *etmv3_cfg) +{ + ocsd_err_t err = OCSD_OK; + if(handle != C_API_INVALID_TREE_HANDLE) + { + EtmV3Config cfg; + cfg = static_cast<const ocsd_etmv3_cfg *>(etmv3_cfg); + + // no need for a spcific CB object here - standard generic elements output used. + if(err == OCSD_OK) + err = ((DecodeTree *)handle)->createETMv3Decoder(&cfg); + } + else + err = OCSD_ERR_INVALID_PARAM_VAL; + return err; +} + OCSD_C_API ocsd_err_t ocsd_dt_attach_etmv3_pkt_mon(const dcd_tree_handle_t handle, const uint8_t trc_chan_id, FnEtmv3PktMonDataIn pPktFn, const void *p_context) { ocsd_err_t err = OCSD_OK; diff --git a/decoder/source/etmv3/trc_pkt_decode_etmv3.cpp b/decoder/source/etmv3/trc_pkt_decode_etmv3.cpp index c5bf8d2..24b753b 100644 --- a/decoder/source/etmv3/trc_pkt_decode_etmv3.cpp +++ b/decoder/source/etmv3/trc_pkt_decode_etmv3.cpp @@ -69,61 +69,47 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV3::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_ASYNC; + resp = sendUnsyncPacket(); + m_curr_state = WAIT_ASYNC; // immediate wait for ASync and actually check out the packet break;
case WAIT_ASYNC: + // if async, wait for ISync, but this packet done. if(m_curr_packet_in->getType() == ETM3_PKT_A_SYNC) m_curr_state = WAIT_ISYNC; bPktDone = true; break;
case WAIT_ISYNC: + m_bWaitISync = true; // we are waiting for ISync if((m_curr_packet_in->getType() == ETM3_PKT_I_SYNC) || (m_curr_packet_in->getType() == ETM3_PKT_I_SYNC_CYCLE)) - m_curr_state = DECODE_PKTS; - else - bPktDone = true; // not I-sync - done. - break; - - case DECODE_PKTS: - resp = decodePacket(); - bPktDone = true; - break; - - case PEND_INSTR: - // check the current packet for cancel - if(!m_curr_packet_in->isExcepCancel()) - // if not output the last instruction - resp = outputTraceElement(m_output_elem); - - if( OCSD_DATA_RESP_IS_CONT(resp)) - m_curr_state = DECODE_PKTS; - else { - pendPacket(); - bPktDone = true; + // process the ISync immediately as the first ISync seen. + resp = processISync((m_curr_packet_in->getType() == ETM3_PKT_I_SYNC_CYCLE),true); + m_curr_state = SEND_PKTS; + m_bWaitISync = false; } - break; - - case PEND_PACKET: + // something like TS, CC, PHDR+CC, which after ASYNC may be valid prior to ISync + else if(preISyncValid(m_curr_packet_in->getType())) { - const EtmV3TrcPacket *p_temp_pkt = m_curr_packet_in; - m_curr_packet_in = &m_pended_packet; - m_curr_state = DECODE_PKTS; - resp = decodePacket(); - m_curr_packet_in = p_temp_pkt; - if(!OCSD_DATA_RESP_IS_CONT(resp)) - { - // previous packet pended returned a wait, so pend current - pendPacket(); - bPktDone = true; - } + // decode anything that might be valid - send will be set automatically + resp = decodePacket(bPktDone); } + else + bPktDone = true; + break; + + case DECODE_PKTS: + resp = decodePacket(bPktDone); break;
+ case SEND_PKTS: + resp = m_outputElemList.sendElements(); + if(OCSD_DATA_RESP_IS_CONT(resp)) + m_curr_state = m_bWaitISync ? WAIT_ISYNC : DECODE_PKTS; + bPktDone = true; + break; } }
@@ -133,7 +119,21 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV3::processPacket() ocsd_datapath_resp_t TrcPktDecodeEtmV3::onEOT() { ocsd_datapath_resp_t resp = OCSD_RESP_CONT; - + OcsdTraceElement *pElem = 0; + try { + pElem = GetNextOpElem(resp); + pElem->setType(OCSD_GEN_TRC_ELEM_EO_TRACE); + m_outputElemList.commitAllPendElem(); + m_curr_state = SEND_PKTS; + resp = m_outputElemList.sendElements(); + if(OCSD_DATA_RESP_IS_CONT(resp)) + m_curr_state = DECODE_PKTS; + } + catch(ocsdError &err) + { + LogError(err); + resetDecoder(); // mark decoder as unsynced - dump any current state. + } return resp; }
@@ -147,7 +147,12 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV3::onReset() ocsd_datapath_resp_t TrcPktDecodeEtmV3::onFlush() { ocsd_datapath_resp_t resp = OCSD_RESP_CONT; - + if(m_curr_state == SEND_PKTS) + { + resp = m_outputElemList.sendElements(); + if(OCSD_DATA_RESP_IS_CONT(resp)) + m_curr_state = m_bWaitISync ? WAIT_ISYNC : DECODE_PKTS; + } return resp; }
@@ -173,6 +178,7 @@ ocsd_err_t TrcPktDecodeEtmV3::onProtocolConfig() arch_profile.profile = m_config->getCoreProfile(); m_code_follower.setArchProfile(arch_profile); m_code_follower.setMemSpaceCSID(m_CSID); + m_outputElemList.initCSID(m_CSID); } else err = OCSD_ERR_NOT_INIT; @@ -187,168 +193,473 @@ void TrcPktDecodeEtmV3::initDecoder() m_CSID = 0; resetDecoder(); m_code_follower.initInterfaces(getMemoryAccessAttachPt(),getInstrDecodeAttachPt()); + m_outputElemList.initSendIf(getTraceElemOutAttachPt()); }
// reset for first use / re-use. void TrcPktDecodeEtmV3::resetDecoder() { m_curr_state = NO_SYNC; // mark as not synced - m_pe_context.resetCtxt(); - m_output_elem.init(); + m_bNeedAddr = true; + m_bSentUnknown = false; + m_bWaitISync = false; + m_outputElemList.reset(); +} + +OcsdTraceElement *TrcPktDecodeEtmV3::GetNextOpElem(ocsd_datapath_resp_t &resp) +{ + OcsdTraceElement *pElem = m_outputElemList.getNextElem(m_index_curr_pkt); + if(pElem == 0) + { + resp = OCSD_RESP_FATAL_NOT_INIT; + throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_MEM,m_index_curr_pkt,m_CSID,"Memory Allocation Error - fatal"); + } + return pElem; +}
+bool TrcPktDecodeEtmV3::preISyncValid(ocsd_etmv3_pkt_type pkt_type) +{ + bool bValid = false; + // its a timestamp + if((pkt_type == ETM3_PKT_TIMESTAMP) || + // or we are cycleacc and its a packet that can have CC in it + (m_config->isCycleAcc() && ((pkt_type == ETM3_PKT_CYCLE_COUNT) || (pkt_type == ETM3_PKT_P_HDR))) + ) + bValid = true; + return bValid; }
// simple packet transforms handled here, more complex processing passed on to specific routines. -ocsd_datapath_resp_t TrcPktDecodeEtmV3::decodePacket() +ocsd_datapath_resp_t TrcPktDecodeEtmV3::decodePacket(bool &pktDone) { ocsd_datapath_resp_t resp = OCSD_RESP_CONT; bool bOutputElem = false; bool bISyncHasCC = false; + OcsdTraceElement *pElem = 0; + pktDone = false;
- switch(m_curr_packet_in->getType()) - { + // there may be pended packets that can now be committed. + // only the branch address with exception and cancel element can cancel + // if not one of those, commit immediately, otherwise defer to branch address handler. + if(m_curr_packet_in->getType() != ETM3_PKT_BRANCH_ADDRESS) + m_outputElemList.commitAllPendElem();
- case ETM3_PKT_NOTSYNC: - // mark as not synced - must have lost sync in the packet processor somehow - LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,m_index_curr_pkt,m_CSID,"Trace Packet Synchronisation Lost")); - resetDecoder(); // mark decoder as unsynced - dump any current state. - break; - - // no action for these packets - ignore and continue - case ETM3_PKT_INCOMPLETE_EOT: - case ETM3_PKT_A_SYNC: - case ETM3_PKT_IGNORE: - break; - -// markers for valid packets - case ETM3_PKT_CYCLE_COUNT: - m_output_elem.setType(OCSD_GEN_TRC_ELEM_CYCLE_COUNT); - m_output_elem.setCycleCount(m_curr_packet_in->getCycleCount()); - bOutputElem = true; - break; - - case ETM3_PKT_TRIGGER: - m_output_elem.setType(OCSD_GEN_TRC_ELEM_EVENT); - m_output_elem.setEvent(EVENT_TRIGGER,0); - bOutputElem = true; - break; - - case ETM3_PKT_BRANCH_ADDRESS: - resp = processBranchAddr(); - break; - - case ETM3_PKT_I_SYNC_CYCLE: - bISyncHasCC = true; - case ETM3_PKT_I_SYNC: - resp = processISync(bISyncHasCC); - break; - - case ETM3_PKT_P_HDR: - resp = processPHdr(); - break; - - case ETM3_PKT_CONTEXT_ID: - m_output_elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); - m_pe_context.setCtxtID(m_curr_packet_in->getCtxtID()); - m_output_elem.setContext(m_pe_context); - bOutputElem = true; - break; - - case ETM3_PKT_VMID: - m_output_elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); - m_pe_context.setVMID(m_curr_packet_in->getVMID()); - m_output_elem.setContext(m_pe_context); - bOutputElem = true; - break; - - case ETM3_PKT_EXCEPTION_ENTRY: - m_output_elem.setType(OCSD_GEN_TRC_ELEM_EXCEPTION); - m_output_elem.setExcepMarker(); // exception entries are always v7M data markers in ETMv3 trace. - bOutputElem = true; - break; - - case ETM3_PKT_EXCEPTION_EXIT: - m_output_elem.setType(OCSD_GEN_TRC_ELEM_EXCEPTION_RET); - bOutputElem = true; - break; - - case ETM3_PKT_TIMESTAMP: - m_output_elem.setType(OCSD_GEN_TRC_ELEM_TIMESTAMP); - m_output_elem.setTS(m_curr_packet_in->getTS()); - bOutputElem = true; - break; - - // data packets - data trace not supported at present - case ETM3_PKT_STORE_FAIL: - case ETM3_PKT_OOO_DATA: - case ETM3_PKT_OOO_ADDR_PLC: - case ETM3_PKT_NORM_DATA: - case ETM3_PKT_DATA_SUPPRESSED: - case ETM3_PKT_VAL_NOT_TRACED: - case ETM3_PKT_BAD_TRACEMODE: - LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,m_index_curr_pkt,m_CSID,"Invalid packet type : Data Tracing decode not supported.")); - resp = OCSD_RESP_FATAL_INVALID_DATA; - resetDecoder(); // mark decoder as unsynced - dump any current state. - break; + try {
+ switch(m_curr_packet_in->getType()) + {
-// packet errors - case ETM3_PKT_BAD_SEQUENCE: - LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,m_index_curr_pkt,m_CSID,"Bad Packet sequence.")); - resp = OCSD_RESP_FATAL_INVALID_DATA; - resetDecoder(); // mark decoder as unsynced - dump any current state. - break; + case ETM3_PKT_NOTSYNC: + // mark as not synced - must have lost sync in the packet processor somehow + throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,m_index_curr_pkt,m_CSID,"Trace Packet Synchronisation Lost"); + break;
- default: - case ETM3_PKT_RESERVED: - LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,m_index_curr_pkt,m_CSID,"Reserved or unknown packet ID.")); - resp = OCSD_RESP_FATAL_INVALID_DATA; - resetDecoder(); // mark decoder as unsynced - dump any current state. - break; - } + // no action for these packets - ignore and continue + case ETM3_PKT_INCOMPLETE_EOT: + case ETM3_PKT_A_SYNC: + case ETM3_PKT_IGNORE: + break; + + // markers for valid packets + case ETM3_PKT_CYCLE_COUNT: + pElem = GetNextOpElem(resp); + pElem->setType(OCSD_GEN_TRC_ELEM_CYCLE_COUNT); + pElem->setCycleCount(m_curr_packet_in->getCycleCount()); + break; + + case ETM3_PKT_TRIGGER: + pElem = GetNextOpElem(resp); + pElem->setType(OCSD_GEN_TRC_ELEM_EVENT); + pElem->setEvent(EVENT_TRIGGER,0); + break; + + case ETM3_PKT_BRANCH_ADDRESS: + resp = processBranchAddr(); + break; + + case ETM3_PKT_I_SYNC_CYCLE: + bISyncHasCC = true; + case ETM3_PKT_I_SYNC: + resp = processISync(bISyncHasCC); + break; + + case ETM3_PKT_P_HDR: + resp = processPHdr(); + break; + + case ETM3_PKT_CONTEXT_ID: + pElem = GetNextOpElem(resp); + pElem->setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); + m_PeContext.setCtxtID(m_curr_packet_in->getCtxtID()); + pElem->setContext(m_PeContext); + break; + + case ETM3_PKT_VMID: + pElem = GetNextOpElem(resp); + pElem->setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); + m_PeContext.setVMID(m_curr_packet_in->getVMID()); + pElem->setContext(m_PeContext); + break; + + case ETM3_PKT_EXCEPTION_ENTRY: + pElem = GetNextOpElem(resp); + pElem->setType(OCSD_GEN_TRC_ELEM_EXCEPTION); + pElem->setExcepMarker(); // exception entries are always v7M data markers in ETMv3 trace. + break; + + case ETM3_PKT_EXCEPTION_EXIT: + pElem = GetNextOpElem(resp); + pElem->setType(OCSD_GEN_TRC_ELEM_EXCEPTION_RET); + pendExceptionReturn(); + break; + + case ETM3_PKT_TIMESTAMP: + pElem = GetNextOpElem(resp); + pElem->setType(OCSD_GEN_TRC_ELEM_TIMESTAMP); + pElem->setTS(m_curr_packet_in->getTS()); + break;
- if(bOutputElem) - resp = outputTraceElementIdx(m_index_curr_pkt,m_output_elem); + // data packets - data trace not supported at present + case ETM3_PKT_STORE_FAIL: + case ETM3_PKT_OOO_DATA: + case ETM3_PKT_OOO_ADDR_PLC: + case ETM3_PKT_NORM_DATA: + case ETM3_PKT_DATA_SUPPRESSED: + case ETM3_PKT_VAL_NOT_TRACED: + case ETM3_PKT_BAD_TRACEMODE: + resp = OCSD_RESP_FATAL_INVALID_DATA; + throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,m_index_curr_pkt,m_CSID,"Invalid packet type : Data Tracing decode not supported."); + break; + + // packet errors + case ETM3_PKT_BAD_SEQUENCE: + resp = OCSD_RESP_FATAL_INVALID_DATA; + throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,m_index_curr_pkt,m_CSID,"Bad Packet sequence."); + break;
+ default: + case ETM3_PKT_RESERVED: + resp = OCSD_RESP_FATAL_INVALID_DATA; + throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,m_index_curr_pkt,m_CSID,"Reserved or unknown packet ID."); + break; + } + m_curr_state = m_outputElemList.elemToSend() ? SEND_PKTS : DECODE_PKTS; + pktDone = !m_outputElemList.elemToSend(); + } + catch(ocsdError &err) + { + LogError(err); + resetDecoder(); // mark decoder as unsynced - dump any current state. + pktDone = true; + } + catch(...) + { + LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_FAIL,m_index_curr_pkt,m_CSID,"Bad Packet sequence.")); + resp = OCSD_RESP_FATAL_SYS_ERR; + resetDecoder(); // mark decoder as unsynced - dump any current state. + pktDone = true; + } + return resp; +} + +ocsd_datapath_resp_t TrcPktDecodeEtmV3::sendUnsyncPacket() +{ + ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + OcsdTraceElement *pElem = 0; + try { + pElem = GetNextOpElem(resp); + pElem->setType(OCSD_GEN_TRC_ELEM_NO_SYNC); + resp = m_outputElemList.sendElements(); + } + catch(ocsdError &err) + { + LogError(err); + resetDecoder(); // mark decoder as unsynced - dump any current state. + } return resp; }
-void TrcPktDecodeEtmV3::pendPacket() +void TrcPktDecodeEtmV3::setNeedAddr(bool bNeedAddr) { - m_pended_packet = *m_curr_packet_in; - m_curr_state = PEND_PACKET; + m_bNeedAddr = bNeedAddr; + m_bSentUnknown = false; } - -ocsd_datapath_resp_t TrcPktDecodeEtmV3::processISync(const bool withCC) + +ocsd_datapath_resp_t TrcPktDecodeEtmV3::processISync(const bool withCC, const bool firstSync /* = false */) { + // map ISync reason to generic reason codes. + static trace_on_reason_t on_map[] = { TRACE_ON_NORMAL, TRACE_ON_NORMAL, + TRACE_ON_OVERFLOW, TRACE_ON_EX_DEBUG }; + ocsd_datapath_resp_t resp = OCSD_RESP_CONT; - // look for context changes.... - if(m_curr_packet_in->isCtxtIDUpdated()) - { + bool ctxtUpdate = m_curr_packet_in->isCtxtUpdated(); + OcsdTraceElement *pElem = 0;
- } + try {
- if(m_config->CtxtIDBytes()) - { + pElem = GetNextOpElem(resp);
- } + if(firstSync || (m_curr_packet_in->getISyncReason() != iSync_Periodic)) + { + pElem->setType(OCSD_GEN_TRC_ELEM_TRACE_ON); + pElem->setTraceOnReason(on_map[(int)m_curr_packet_in->getISyncReason()]); + pElem = GetNextOpElem(resp); + } + + // look for context changes.... + if(ctxtUpdate || firstSync) + { + // if not first time out, read existing context in output element, + // otherwise we are setting it new. + if(firstSync) + m_PeContext.resetCtxt(); + + if(m_curr_packet_in->isCtxtIDUpdated()) + m_PeContext.setCtxtID(m_curr_packet_in->getCtxtID()); + if(m_curr_packet_in->isVMIDUpdated()) + m_PeContext.setVMID(m_curr_packet_in->getVMID()); + if(m_curr_packet_in->isCtxtFlagsUpdated()) + { + m_PeContext.setEL(m_curr_packet_in->isHyp() ? ocsd_EL2 : ocsd_EL_unknown); + m_PeContext.setSecLevel(m_curr_packet_in->isNS() ? ocsd_sec_nonsecure : ocsd_sec_secure); + } + + // prepare the context packet + pElem->setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); + pElem->setContext(m_PeContext); + pElem->setISA(m_curr_packet_in->ISA()); + + // with cycle count... + if(m_curr_packet_in->getISyncHasCC()) + pElem->setCycleCount(m_curr_packet_in->getCycleCount()); + + } + + // set ISync address - if it is a valid I address + if(!m_curr_packet_in->getISyncNoAddr()) + { + if(m_curr_packet_in->getISyncIsLSiPAddr()) + { + // TBD: handle extra data processing instruction for data trace + // need to output E atom relating to the data instruction + // rare - on start-up case.
+ // main instruction address saved in data address for this packet type. + m_IAddr = m_curr_packet_in->getDataAddr(); + } + else + { + m_IAddr = m_curr_packet_in->getAddr(); + } + setNeedAddr(false); // ready to process atoms. + } + m_curr_state = m_outputElemList.elemToSend() ? SEND_PKTS : DECODE_PKTS; + } + catch(ocsdError &err) + { + LogError(err); + resetDecoder(); // mark decoder as unsynced - dump any current state. + } return resp; }
ocsd_datapath_resp_t TrcPktDecodeEtmV3::processBranchAddr() { ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + OcsdTraceElement *pElem = 0; + bool bUpdatePEContext = false; + + // might need to cancel something ... if the last output was an instruction range or excep return + if(m_curr_packet_in->isExcepCancel()) + m_outputElemList.cancelPendElem(); + else + m_outputElemList.commitAllPendElem(); // otherwise commit any pending elements. + + // record the address + m_IAddr = m_curr_packet_in->getAddr(); + setNeedAddr(false); // no longer need an address. + + // exception packet - may need additional output + if(m_curr_packet_in->isExcepPkt()) + { + // exeception packet may have exception, context change, or both. + // check for context change + if(m_curr_packet_in->isCtxtUpdated()) + { + + ocsd_sec_level sec = m_curr_packet_in->isNS() ? ocsd_sec_nonsecure : ocsd_sec_secure; + if(sec != m_PeContext.getSecLevel()) + { + m_PeContext.setSecLevel(sec); + bUpdatePEContext = true; + } + ocsd_ex_level pkt_el = m_curr_packet_in->isHyp() ? ocsd_EL2 : ocsd_EL_unknown; + if(pkt_el != m_PeContext.getEL()) + { + m_PeContext.setEL(pkt_el); + bUpdatePEContext = true; + } + } + + // now decide if we need to send any packets out. + try { + + if(bUpdatePEContext) + { + pElem = GetNextOpElem(resp); + pElem->setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); + pElem->setContext(m_PeContext); + } + + // check for exception + if(m_curr_packet_in->excepNum() != 0) + { + pElem = GetNextOpElem(resp); + pElem->setType(OCSD_GEN_TRC_ELEM_EXCEPTION); + pElem->setExceptionNum(m_curr_packet_in->excepNum()); + }
+ // finally - do we have anything to send yet? + m_curr_state = m_outputElemList.elemToSend() ? SEND_PKTS : DECODE_PKTS; + } + catch(ocsdError &err) + { + LogError(err); + resetDecoder(); // mark decoder as unsynced - dump any current state. + } + } return resp; }
+ ocsd_datapath_resp_t TrcPktDecodeEtmV3::processPHdr() { ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + OcsdTraceElement *pElem = 0; + uint32_t CC = 0; + ocsd_isa isa; + Etmv3Atoms atoms(m_config->isCycleAcc()); + + atoms.initAtomPkt(m_curr_packet_in,m_index_curr_pkt); + isa = m_curr_packet_in->ISA(); + m_code_follower.setMemSpaceAccess((m_PeContext.getSecLevel() == ocsd_sec_secure) ? OCSD_MEM_SPACE_S : OCSD_MEM_SPACE_N); + + try + { + do + { + // if we do not have a valid address then send any cycle count elements + // and stop processing + if(m_bNeedAddr) + { + // output unknown address packet or a cycle count packet + if(!m_bSentUnknown || m_config->isCycleAcc()) + { + pElem = GetNextOpElem(resp); + if(m_bSentUnknown || !atoms.numAtoms()) + pElem->setType(OCSD_GEN_TRC_ELEM_CYCLE_COUNT); + else + pElem->setType(OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN); + if(m_config->isCycleAcc()) + pElem->setCycleCount(atoms.getRemainCC()); + m_bSentUnknown = true; + } + atoms.clearAll(); // skip remaining atoms + } + else // have an address, can process atoms + { + pElem = GetNextOpElem(resp); + pElem->setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE); + + // cycle accurate may have a cycle count to use + if(m_config->isCycleAcc()) + { + // note: it is possible to have a CC only atom packet. + if(!atoms.numAtoms()) // override type if CC only + pElem->setType(OCSD_GEN_TRC_ELEM_CYCLE_COUNT); + // set cycle count + pElem->setCycleCount(atoms.getAtomCC()); + } + + // now process the atom + if(atoms.numAtoms()) + { + m_code_follower.setISA(isa); + m_code_follower.followSingleAtom(m_IAddr,atoms.getCurrAtomVal()); + + // valid code range + if(m_code_follower.hasRange()) + { + pElem->setAddrRange(m_IAddr,m_code_follower.getRangeEn()); + pElem->setLastInstrInfo(atoms.getCurrAtomVal() == ATOM_E, + m_code_follower.getInstrType(), + m_code_follower.getInstrSubType()); + pElem->setISA(isa); + if(m_code_follower.hasNextAddr()) + m_IAddr = m_code_follower.getNextAddr(); + else + setNeedAddr(true); + } + + // next address has new ISA? + if(m_code_follower.ISAChanged()) + isa = m_code_follower.nextISA(); + + // there is a nacc + if(m_code_follower.isNacc()) + { + if(m_code_follower.hasRange()) + { + pElem = GetNextOpElem(resp); + pElem->setType(OCSD_GEN_TRC_ELEM_ADDR_NACC); + } + else + pElem->updateType(OCSD_GEN_TRC_ELEM_ADDR_NACC); + pElem->setAddrStart(m_code_follower.getNaccAddr()); + setNeedAddr(true); + m_code_follower.clearNacc(); // we have generated some code for the nacc. + } + } + + atoms.clearAtom(); // next atom + } + } + while(atoms.numAtoms()); + + // is tha last element an atom? + int numElem = m_outputElemList.getNumElem(); + if(numElem >= 1) + { + // if the last thing is an instruction range, pend it - could be cancelled later. + if(m_outputElemList.getElemType(numElem-1) == OCSD_GEN_TRC_ELEM_INSTR_RANGE) + m_outputElemList.pendLastNElem(1); + }
+ // finally - do we have anything to send yet? + m_curr_state = m_outputElemList.elemToSend() ? SEND_PKTS : DECODE_PKTS; + } + catch(ocsdError &err) + { + LogError(err); + resetDecoder(); // mark decoder as unsynced - dump any current state. + } return resp; }
+// if v7M -> pend only ERET, if V7A/R pend ERET and prev instr. +void TrcPktDecodeEtmV3::pendExceptionReturn() +{ + int pendElem = 1; + if(m_config->getCoreProfile() != profile_CortexM) + { + int nElem = m_outputElemList.getNumElem(); + if(nElem > 1) + { + if(m_outputElemList.getElemType(nElem - 2) == OCSD_GEN_TRC_ELEM_INSTR_RANGE) + pendElem = 2; // need to pend instr+eret for A/R + } + } + m_outputElemList.pendLastNElem(pendElem); +}
/* End of File trc_pkt_decode_etmv3.cpp */ diff --git a/decoder/source/ocsd_code_follower.cpp b/decoder/source/ocsd_code_follower.cpp index b52704e..b03ec1a 100644 --- a/decoder/source/ocsd_code_follower.cpp +++ b/decoder/source/ocsd_code_follower.cpp @@ -99,7 +99,7 @@ ocsd_err_t OcsdCodeFollower::followSingleAtom(const ocsd_vaddr_t addrStart, cons ocsd_err_t err = OCSD_ERR_NOT_INIT; if(initFollowerState()) { - m_st_range_addr = m_instr_info.instr_addr = addrStart; + m_en_range_addr = m_st_range_addr = m_instr_info.instr_addr = addrStart; err = decodeSingleOpCode(); if(err == OCSD_OK) { @@ -128,7 +128,6 @@ ocsd_err_t OcsdCodeFollower::followSingleAtom(const ocsd_vaddr_t addrStart, cons return err; }
- ocsd_err_t OcsdCodeFollower::decodeSingleOpCode() { ocsd_err_t err = OCSD_OK; diff --git a/decoder/source/ocsd_dcd_tree.cpp b/decoder/source/ocsd_dcd_tree.cpp index cf5a30d..8f14af1 100644 --- a/decoder/source/ocsd_dcd_tree.cpp +++ b/decoder/source/ocsd_dcd_tree.cpp @@ -61,7 +61,7 @@ void DecodeTreeElement::DestroyElem() case OCSD_PROTOCOL_ETMV3: delete decoder.etmv3.proc; decoder.etmv3.proc = 0; - //TBD: delete decoder.etmv3.dcd; + delete decoder.etmv3.dcd; decoder.etmv3.dcd = 0; break;
@@ -533,16 +533,33 @@ ocsd_err_t DecodeTree::createSTMPktProcessor(STMConfig *p_config, IPktDataIn<Stm ocsd_err_t DecodeTree::createETMv3Decoder(EtmV3Config *p_config) { ocsd_err_t err = OCSD_ERR_NOT_INIT; -#if 0 //TBD: uint8_t CSID = 0; // default for single stream decoder (no deformatter) - we ignore the ID if(usingFormatter()) CSID = p_config->getTraceID(); - /* err = */ createETMv3PktProcessor(p_config); - if(err == OCSD_OK) // created the packet processor and the decoder element*/ + + TrcPktDecodeEtmV3 *pProc = 0; + pProc = new (std::nothrow) TrcPktDecodeEtmV3(CSID); + if(!pProc) + return OCSD_ERR_MEM; + + err = createETMv3PktProcessor(p_config,pProc); + if(err == OCSD_OK) { - //** TBD + m_decode_elements[CSID]->SetDecoderElement(pProc); + err = pProc->setProtocolConfig(p_config); + if(m_i_instr_decode && (err == OCSD_OK)) + err = pProc->getInstrDecodeAttachPt()->attach(m_i_instr_decode); + if(m_i_mem_access && (err == OCSD_OK)) + err = pProc->getMemoryAccessAttachPt()->attach(m_i_mem_access); + if( m_i_gen_elem_out && (err == OCSD_OK)) + err = pProc->getTraceElemOutAttachPt()->attach(m_i_gen_elem_out); + if(err == OCSD_OK) + err = pProc->getErrorLogAttachPt()->attach(DecodeTree::s_i_error_logger); + + if(err != OCSD_OK) + destroyDecodeElement(CSID); } -#endif + return err; }
diff --git a/decoder/source/ocsd_error.cpp b/decoder/source/ocsd_error.cpp index 844fca5..a94b7b2 100644 --- a/decoder/source/ocsd_error.cpp +++ b/decoder/source/ocsd_error.cpp @@ -66,10 +66,11 @@ static const char *s_errorCodeDescs[][2] = { {"OCSD_ERR_PKT_INTERP_FAIL","Interpreter failed - cannot recover - bad data or sequence"}, /* packet decoder errors */ {"OCSD_ERR_UNSUPPORTED_ISA","ISA not supported in decoder"}, - {"OCSD_ERR_HW_CFG_UNSUPP","Programmed trace configuration not supported by decoder."}, + {"OCSD_ERR_HW_CFG_UNSUPP","Programmed trace configuration not supported by decodUer."}, {"OCSD_ERR_UNSUPP_DECODE_PKT","Packet not supported in decoder"}, {"OCSD_ERR_BAD_DECODE_PKT","Reserved or unknown packet in decoder."}, {"OCSD_ERR_COMMIT_PKT_OVERRUN","Overrun in commit packet stack - tried to commit more than available"}, + {"OCSD_ERR_MEM_NACC","Unable to access required memory address."}, /* decode tree errors */ {"OCSD_ERR_DCDT_NO_FORMATTER","No formatter in use - operation not valid."}, /* target memory access errors */ diff --git a/decoder/source/ocsd_gen_elem_list.cpp b/decoder/source/ocsd_gen_elem_list.cpp new file mode 100644 index 0000000..1a568ec --- /dev/null +++ b/decoder/source/ocsd_gen_elem_list.cpp @@ -0,0 +1,168 @@ +/* + * \file ocsd_gen_elem_list.cpp + * \brief OpenCSD : List of Generic trace elements for output. + * + * \copyright Copyright (c) 2016, 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_list.h" + +OcsdGenElemList::OcsdGenElemList() +{ + m_firstElemIdx=0; + m_numUsed=0; + m_numPend=0; + + m_elemArraySize = 0; + m_sendIf = 0; + m_CSID = 0; + m_pElemArray = 0; +} + +OcsdGenElemList::~OcsdGenElemList() +{ + for(int i = 0; i<m_elemArraySize; i++) + { + delete m_pElemArray[i].pElem; + } + delete [] m_pElemArray; + m_pElemArray = 0; +} + +void OcsdGenElemList::reset() +{ + m_firstElemIdx=0; + m_numUsed=0; + m_numPend=0; +} + +OcsdTraceElement *OcsdGenElemList::getNextElem(const ocsd_trc_index_t trc_pkt_idx) +{ + OcsdTraceElement *pElem = 0; + if(getNumElem() == m_elemArraySize) // all in use + growArray(); + + if(m_pElemArray != 0) + { + m_numUsed++; + int idx = getAdjustedIdx(m_firstElemIdx + m_numUsed - 1); + pElem = m_pElemArray[idx].pElem; + m_pElemArray[idx].trc_pkt_idx = trc_pkt_idx; + } + return pElem; +} + +const ocsd_gen_trc_elem_t OcsdGenElemList::getElemType(const int entryN) const +{ + ocsd_gen_trc_elem_t elem_type = OCSD_GEN_TRC_ELEM_UNKNOWN; + if(entryN < getNumElem()) + { + int idx = getAdjustedIdx(m_firstElemIdx + entryN); + elem_type = m_pElemArray[idx].pElem->getType(); + } + return elem_type; +} + +ocsd_datapath_resp_t OcsdGenElemList::sendElements() +{ + ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + + if((m_elemArraySize == 0) || (m_sendIf == 0)) + return OCSD_RESP_FATAL_NOT_INIT; + + if(!m_sendIf->hasAttachedAndEnabled()) + return OCSD_RESP_FATAL_NOT_INIT; + + while(elemToSend() && OCSD_DATA_RESP_IS_CONT(resp)) + { + resp = m_sendIf->first()->TraceElemIn(m_pElemArray[m_firstElemIdx].trc_pkt_idx, m_CSID, *(m_pElemArray[m_firstElemIdx].pElem)); + m_firstElemIdx++; + if(m_firstElemIdx >= m_elemArraySize) + m_firstElemIdx = 0; + m_numUsed--; + } + return resp; +} + +// this function will enlarge the array, and create extra element objects. +// existing objects will be moved to the front of the array +// called if all elements are in use. (sets indexes accordingly) +void OcsdGenElemList::growArray() +{ + elemPtr_t *p_new_array = 0; + + int increment; + if(m_elemArraySize == 0) + // starting from scratch... + increment = 8; + else + increment = m_elemArraySize / 2; // grow by 50% + + + p_new_array = new (std::nothrow) elemPtr_t[m_elemArraySize+increment]; + + if(p_new_array != 0) + { + // fill the last increment elements with new objects + for(int i=0; i < increment; i++) + { + p_new_array[m_elemArraySize+i].pElem = new (std::nothrow) OcsdTraceElement(); + } + + // copy the existing objects from the old array to the start of the new one + // and adjust the indices. + if(m_elemArraySize > 0) + { + int inIdx = m_firstElemIdx; + for(int i = 0; i < m_elemArraySize; i++) + { + p_new_array[i].pElem = m_pElemArray[inIdx].pElem; + p_new_array[i].trc_pkt_idx = m_pElemArray[inIdx].trc_pkt_idx; + inIdx++; + if(inIdx >= m_elemArraySize) + inIdx = 0; + } + } + + // delete the old pointer array. + delete [] m_pElemArray; + m_elemArraySize += increment; + } + else + m_elemArraySize = 0; + + // update the internal array pointers to the new array + if(m_firstElemIdx >= 0) + m_firstElemIdx = 0; + m_pElemArray = p_new_array; +} + +/* End of File ocsd_gen_elem_list.cpp */ diff --git a/decoder/source/trc_gen_elem.cpp b/decoder/source/trc_gen_elem.cpp index 912760d..aef8820 100644 --- a/decoder/source/trc_gen_elem.cpp +++ b/decoder/source/trc_gen_elem.cpp @@ -47,6 +47,7 @@ static const char *s_elem_descs[][2] = {"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_ADDR_NACC","Tracing in inaccessible memory area."}, + {"OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN","Tracing unknown address area."}, {"OCSD_GEN_TRC_ELEM_EXCEPTION","Exception"}, {"OCSD_GEN_TRC_ELEM_EXCEPTION_RET","Expection return"}, {"OCSD_GEN_TRC_ELEM_TIMESTAMP","Timestamp - preceding elements happeded before this time."}, @@ -79,6 +80,16 @@ static const char *s_trace_on_reason[] = { "debug restart" };
+ +static const char *s_isa_str[] = { + "A32", /**< V7 ARM 32, V8 AArch32 */ + "T32", /**< Thumb2 -> 16/32 bit instructions */ + "A64", /**< V8 AArch64 */ + "TEE", /**< Thumb EE - unsupported */ + "Jaz", /**< Jazelle - unsupported in trace */ + "Unk" /**< ISA not yet known */ +}; + void OcsdTraceElement::toString(std::string &str) const { std::ostringstream oss; @@ -91,6 +102,7 @@ void OcsdTraceElement::toString(std::string &str) const { case OCSD_GEN_TRC_ELEM_INSTR_RANGE: oss << "exec range=0x" << std::hex << st_addr << ":[0x" << en_addr << "] "; + oss << "(ISA=" << s_isa_str[(int)isa] << ") "; oss << ((last_instr_exec == 1) ? "E " : "N "); if((int)last_i_type < T_SIZE) oss << instr_type[last_i_type]; @@ -111,7 +123,12 @@ void OcsdTraceElement::toString(std::string &str) const break;
case OCSD_GEN_TRC_ELEM_PE_CONTEXT: - oss << "EL" << std::dec << (int)(context.exception_level) << (context.security_level == ocsd_sec_secure ? " S; " : "N; ") << (context.bits64 ? "AArch64; " : "AArch32; "); + oss << "(ISA=" << s_isa_str[(int)isa] << ") "; + if(context.exception_level >= 0) + { + oss << "EL" << std::dec << (int)(context.exception_level); + } + oss << (context.security_level == ocsd_sec_secure ? " S; " : "N; ") << (context.bits64 ? "64-bit; " : "32-bit; "); if(context.vmid_valid) oss << "VMID=0x" << std::hex << context.vmid << "; "; if(context.ctxt_id_valid) diff --git a/decoder/tests/source/simple_pkt_c_api.c b/decoder/tests/source/simple_pkt_c_api.c index 45c2611..6c6e503 100644 --- a/decoder/tests/source/simple_pkt_c_api.c +++ b/decoder/tests/source/simple_pkt_c_api.c @@ -62,7 +62,8 @@ const char *tc2_snapshot = "../../../snapshots/TC2/"; const char *trace_data_filename = "cstrace.bin"; const char *stmtrace_data_filename = "cstraceitm.bin"; const char *memory_dump_filename = "kernel_dump.bin"; -const ocsd_vaddr_t mem_dump_address=0xFFFFFFC000081000; +ocsd_vaddr_t mem_dump_address=0xFFFFFFC000081000; +const ocsd_vaddr_t mem_dump_address_tc2=0xC0008000;
static int using_mem_acc_cb = 0; static int use_region_file = 0; @@ -150,11 +151,13 @@ static void process_cmd_line(int argc, char *argv[]) { test_protocol = OCSD_PROTOCOL_ETMV3; default_path_to_snapshot = tc2_snapshot; + mem_dump_address = mem_dump_address_tc2; } else if(strcmp(argv[idx],"-ptm") == 0) { test_protocol = OCSD_PROTOCOL_PTM; default_path_to_snapshot = tc2_snapshot; + mem_dump_address = mem_dump_address_tc2; } else if(strcmp(argv[idx],"-stm") == 0) { @@ -506,7 +509,8 @@ ocsd_datapath_resp_t etm_v3_packet_handler(const void *p_context, const ocsd_dat return packet_handler(op,index_sop,(const void *)p_packet_in); }
-void etm_v3_packet_monitor( const ocsd_datapath_op_t op, +void etm_v3_packet_monitor( const void *p_context, + const ocsd_datapath_op_t op, const ocsd_trc_index_t index_sop, const ocsd_etmv3_pkt *p_packet_in, const uint32_t size, @@ -518,7 +522,7 @@ void etm_v3_packet_monitor( const ocsd_datapath_op_t op, static ocsd_err_t create_decoder_etmv3(dcd_tree_handle_t dcd_tree_h) { ocsd_err_t ret = OCSD_OK; - /*char mem_file_path[512];*/ + char mem_file_path[512];
/* populate the ETMv3 configuration structure */ set_config_struct_etmv3(); @@ -536,14 +540,14 @@ static ocsd_err_t create_decoder_etmv3(dcd_tree_handle_t dcd_tree_h) /* Full decode - need decoder, and memory dump */ /* not supported in library at present */
-#if 0 + /* create the packet decoder and packet processor pair */ ret = ocsd_dt_create_etmv3_decoder(dcd_tree_h,&trace_config_etmv3); if(ret == OCSD_OK) { if((op != TEST_PKT_DECODEONLY) && (ret == OCSD_OK)) { - ret = ocsd_dt_attach_etmv3_pkt_mon(dcd_tree_h, (uint8_t)(trace_config_etmv3.reg_trc_id & 0x7F), etm_v4i_packet_monitor); + ret = ocsd_dt_attach_etmv3_pkt_mon(dcd_tree_h, (uint8_t)(trace_config_etmv3.reg_trc_id & 0x7F), etm_v3_packet_monitor,0); } }
@@ -556,10 +560,6 @@ static ocsd_err_t create_decoder_etmv3(dcd_tree_handle_t dcd_tree_h) /* create a memory file accessor */ ret = ocsd_dt_add_binfile_mem_acc(dcd_tree_h,mem_dump_address,OCSD_MEM_SPACE_ANY,mem_file_path); } -#else - printf("ETMv3 Full decode not supported in library at present. Packet print only\n"); - ret = OCSD_ERR_RDR_NO_DECODER; -#endif } return ret; }