diff options
Diffstat (limited to 'decoder/include/opencsd/etmv4')
-rw-r--r-- | decoder/include/opencsd/etmv4/etmv4_decoder.h | 1 | ||||
-rw-r--r-- | decoder/include/opencsd/etmv4/trc_etmv4_stack_elem.h | 99 | ||||
-rw-r--r-- | decoder/include/opencsd/etmv4/trc_pkt_decode_etmv4i.h | 131 | ||||
-rw-r--r-- | decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4d.h | 73 | ||||
-rw-r--r-- | decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4i.h | 40 | ||||
-rw-r--r-- | decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4.h | 63 | ||||
-rw-r--r-- | decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4i.h | 214 | ||||
-rw-r--r-- | decoder/include/opencsd/etmv4/trc_pkt_types_etmv4.h | 3 |
8 files changed, 424 insertions, 200 deletions
diff --git a/decoder/include/opencsd/etmv4/etmv4_decoder.h b/decoder/include/opencsd/etmv4/etmv4_decoder.h index 05bdd44d683e..5d183631a721 100644 --- a/decoder/include/opencsd/etmv4/etmv4_decoder.h +++ b/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/decoder/include/opencsd/etmv4/trc_etmv4_stack_elem.h b/decoder/include/opencsd/etmv4/trc_etmv4_stack_elem.h index 15996547163c..5a283c541f3e 100644 --- a/decoder/include/opencsd/etmv4/trc_etmv4_stack_elem.h +++ b/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; @@ -120,6 +121,44 @@ inline TrcStackElemAddr::TrcStackElemAddr(const ocsd_etmv4_i_pkt_type root_pkt, } /************************************************************/ +/** 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 */ class TrcStackElemCtxt : public TrcStackElem @@ -133,9 +172,12 @@ protected: 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 @@ public: 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 @@ public: 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 @@ public: 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<TrcStackElem *> m_P0_stack; //!< P0 decode element stack std::vector<TrcStackElem *> m_popped_elem; //!< save list of popped but not deleted elements. - + std::deque<TrcStackElem *>::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/decoder/include/opencsd/etmv4/trc_pkt_decode_etmv4i.h b/decoder/include/opencsd/etmv4/trc_pkt_decode_etmv4i.h index 1c06e5ddf03a..419cd828928c 100644 --- a/decoder/include/opencsd/etmv4/trc_pkt_decode_etmv4i.h +++ b/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 @@ protected: /* 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; + + typedef struct { + ocsd_vaddr_t st_addr; + ocsd_vaddr_t en_addr; + uint32_t num_instr; + } instr_range_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. + //!< 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 returnStackPop(); // pop return stack and update instruction address. + 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. - ocsd_datapath_resp_t outputTraceRange(const bool executed, ocsd_trc_index_t index); + 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 @@ private: 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 @@ private: 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 @@ private: 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/decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4d.h b/decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4d.h deleted file mode 100644 index bb6a0029c0c0..000000000000 --- a/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/decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4i.h b/decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4i.h index 02adfc51aa75..8ccf36b373db 100644 --- a/decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4i.h +++ b/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 @@ public: } } + // 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 @@ public: // 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 @@ public: // 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/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4.h b/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4.h index 0d9ccea2be54..25bdf5109558 100644 --- a/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4.h +++ b/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/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4i.h b/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4i.h new file mode 100644 index 000000000000..abc322654b8d --- /dev/null +++ b/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4i.h @@ -0,0 +1,214 @@ +/* + * \file trc_pkt_proc_etmv4i.h + * \brief OpenCSD : Implementation of ETMv4 packet processing + * + * \copyright Copyright (c) 2015, 2019 ARM Limited. All Rights Reserved. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ARM_TRC_PKT_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 EtmV4ITrcPacket; +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; + +protected: + typedef enum _process_state { + PROC_HDR, + PROC_DATA, + SEND_PKT, + SEND_UNSYNCED, + PROC_ERR, + } process_state; + + process_state m_process_state; + + void InitPacketState(); // clear current packet state. + void InitProcessorState(); // clear all previous process state + + /** packet processor configuration **/ + bool m_isInit; + + // etmv4 hardware configuration + EtmV4Config m_config; + + /** packet data **/ + TraceRawBuffer m_trcIn; // trace data in buffer + std::vector<uint8_t> m_currPacketData; // raw data packet + 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 + ocsd_trc_index_t m_blockIndex; // index at the start of the current data block being processed + + // searching for sync + bool m_is_sync; //!< seen first sync packet + bool m_first_trace_info; //!< seen first trace info packet after sync + bool m_sent_notsync_packet; //!< send one not sync packet if we see any unsynced data on the channel + unsigned m_dump_unsynced_bytes; //!< number of unsynced bytes to send + ocsd_trc_index_t m_update_on_unsync_packet_index; + + +private: + // current processing state data - counts and flags to determine if a packet is complete. + + // TraceInfo Packet + // flags to indicate processing progress for these sections is complete. + struct _t_info_pkt_prog { + uint8_t sectFlags; + uint8_t ctrlBytes; + } m_tinfo_sections; + + #define TINFO_INFO_SECT 0x01 + #define TINFO_KEY_SECT 0x02 + #define TINFO_SPEC_SECT 0x04 + #define TINFO_CYCT_SECT 0x08 + #define TINFO_CTRL 0x20 + #define TINFO_ALL_SECT 0x1F + #define TINFO_ALL 0x3F + + + // address and context packets + int m_addrBytes; + uint8_t m_addrIS; + bool m_bAddr64bit; + int m_vmidBytes; // bytes still to find + int m_ctxtidBytes; // bytes still to find + bool m_bCtxtInfoDone; + bool m_addr_done; + + // timestamp + bool m_ccount_done; // done or not needed + bool m_ts_done; + int m_ts_bytes; + + // exception + int m_excep_size; + + // cycle count + bool m_has_count; + bool m_count_done; + bool m_commit_done; + + // cond result + bool m_F1P1_done; // F1 payload 1 done + bool m_F1P2_done; // F1 payload 2 done + bool m_F1has_P2; // F1 has a payload 2 + + // Q packets (use some from above too) + bool m_has_addr; + bool m_addr_short; + bool m_addr_match; + uint8_t m_Q_type; + uint8_t m_QE; + + ocsd_datapath_resp_t outputPacket(); + ocsd_datapath_resp_t outputUnsyncedRawPacket(); + + void iNotSync(const uint8_t lastByte); // not synced yet + void iPktNoPayload(const uint8_t lastByte); // process a single byte packet + void iPktReserved(const uint8_t lastByte); // deal with reserved header value + void iPktExtension(const uint8_t lastByte); + void iPktASync(const uint8_t lastByte); + void iPktTraceInfo(const uint8_t lastByte); + void iPktTimestamp(const uint8_t lastByte); + void iPktException(const uint8_t lastByte); + void iPktCycleCntF123(const uint8_t lastByte); + void iPktSpeclRes(const uint8_t lastByte); + void iPktCondInstr(const uint8_t lastByte); + void iPktCondResult(const uint8_t lastByte); + void iPktContext(const uint8_t lastByte); + void iPktAddrCtxt(const uint8_t lastByte); + void iPktShortAddr(const uint8_t lastByte); + void iPktLongAddr(const uint8_t lastByte); + void iPktQ(const uint8_t lastByte); + void iAtom(const uint8_t lastByte); + void iPktInvalidCfg(const uint8_t lastByte); // packet invalid in current config. + + unsigned extractContField(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint32_t &value, const unsigned byte_limit = 5); + unsigned extractContField64(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint64_t &value, const unsigned byte_limit = 9); + unsigned extractCondResult(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint32_t& key, uint8_t &result); + void extractAndSetContextInfo(const std::vector<uint8_t> &buffer, const int st_idx); + int extract64BitLongAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint64_t &value); + int extract32BitLongAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint32_t &value); + int extractShortAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint32_t &value, int &bits); + + // packet processing is table driven. + typedef void (TrcPktProcEtmV4I::*PPKTFN)(uint8_t); + PPKTFN m_pIPktFn; + + struct _pkt_i_table_t { + ocsd_etmv4_i_pkt_type pkt_type; + PPKTFN pptkFn; + } m_i_table[256]; + + void BuildIPacketTable(); + + void throwBadSequenceError(const char *pszExtMsg); +}; + + +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/decoder/include/opencsd/etmv4/trc_pkt_types_etmv4.h b/decoder/include/opencsd/etmv4/trc_pkt_types_etmv4.h index dd69a4bf6778..7e98050c77c4 100644 --- a/decoder/include/opencsd/etmv4/trc_pkt_types_etmv4.h +++ b/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 */ |