diff options
Diffstat (limited to 'decoder/source')
22 files changed, 1439 insertions, 280 deletions
diff --git a/decoder/source/c_api/ocsd_c_api.cpp b/decoder/source/c_api/ocsd_c_api.cpp index 4824c427e3d1..750c847e78c8 100644 --- a/decoder/source/c_api/ocsd_c_api.cpp +++ b/decoder/source/c_api/ocsd_c_api.cpp @@ -234,8 +234,24 @@ OCSD_C_API ocsd_err_t ocsd_dt_attach_packet_callback(  const dcd_tree_handle_t h      return err;  } -/*** Decode tree set element output */ +OCSD_C_API ocsd_err_t ocsd_dt_get_decode_stats(const dcd_tree_handle_t handle, +                                               const unsigned char CSID,                                                +                                               ocsd_decode_stats_t **p_stats_block) +{ +    DecodeTree *pDT = static_cast<DecodeTree *>(handle); +     +    return pDT->getDecoderStats(CSID, p_stats_block); +} + +OCSD_C_API ocsd_err_t ocsd_dt_reset_decode_stats(const dcd_tree_handle_t handle, +                                                 const unsigned char CSID) +{ +    DecodeTree *pDT = static_cast<DecodeTree *>(handle); + +    return pDT->resetDecoderStats(CSID); +} +/*** Decode tree set element output */  OCSD_C_API ocsd_err_t ocsd_dt_set_gen_elem_outfn(const dcd_tree_handle_t handle, FnTraceElemIn pFn, const void *p_context)  { @@ -470,6 +486,39 @@ OCSD_C_API ocsd_err_t ocsd_dt_set_pkt_protocol_printer(const dcd_tree_handle_t h      return err;  } +OCSD_C_API void ocsd_err_str(const ocsd_err_t err, char *buffer, const int buffer_size) +{ +    std::string err_str; +    err_str = ocsdError::getErrorString(ocsdError(OCSD_ERR_SEV_ERROR, err)); +    strncpy(buffer, err_str.c_str(), buffer_size - 1); +    buffer[buffer_size - 1] = 0; +} + +OCSD_C_API ocsd_err_t ocsd_get_last_err(ocsd_trc_index_t *index, uint8_t *chan_id, char *message, const int message_len) +{ +    ocsdError *p_err; +    ocsd_err_t err = OCSD_OK; +    std::string err_str; + +    p_err = DecodeTree::getDefaultErrorLogger()->GetLastError(); +    if (p_err)  +    { +        *index = p_err->getErrorIndex(); +        *chan_id = p_err->getErrorChanID(); +        err_str = p_err->getErrorString(ocsdError(p_err)); +        strncpy(message, err_str.c_str(), message_len - 1); +        message[message_len - 1] = 0; +        err = p_err->getErrorCode(); +    } +    else +    { +        message[0] = 0; +        *index = OCSD_BAD_TRC_INDEX; +        *chan_id = OCSD_BAD_CS_SRC_ID; +    } +    return err; +} +  /*******************************************************************************/  /* C API local fns                                                             */  /*******************************************************************************/ diff --git a/decoder/source/ete/trc_cmp_cfg_ete.cpp b/decoder/source/ete/trc_cmp_cfg_ete.cpp new file mode 100644 index 000000000000..474cb2f7914a --- /dev/null +++ b/decoder/source/ete/trc_cmp_cfg_ete.cpp @@ -0,0 +1,98 @@ +/* +* \file       trc_cmp_cfg_ete.cpp +* \brief      OpenCSD : ETE config class +* +* \copyright  Copyright (c) 2019, ARM Limited. All Rights Reserved. +*/ + +/* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software without +* specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "opencsd/ete/trc_cmp_cfg_ete.h" + +ETEConfig::ETEConfig() : EtmV4Config() +{ +    m_ete_cfg.reg_idr0 = 0x28000EA1; +    m_ete_cfg.reg_idr1 = 0x4100FFF3; +    m_ete_cfg.reg_idr2 = 0x00000488; +    m_ete_cfg.reg_idr8 = 0; +    m_ete_cfg.reg_configr = 0xC1; +    m_ete_cfg.reg_traceidr = 0; +    m_ete_cfg.arch_ver = ARCH_AA64; +    m_ete_cfg.core_prof = profile_CortexA; +    m_ete_cfg.reg_devarch = 0x47705A13; +    copyV4(); +} + +ETEConfig::ETEConfig(const ocsd_ete_cfg *cfg_regs) : EtmV4Config() +{ +    m_ete_cfg = *cfg_regs; +    copyV4(); +} + +ETEConfig::~ETEConfig() +{ + +} + +//! copy assignment operator for base structure into class. +ETEConfig & ETEConfig::operator=(const ocsd_ete_cfg *p_cfg) +{ +    m_ete_cfg = *p_cfg; +    copyV4(); +    return *this; +} + +//! cast operator returning struct const reference +//operator const ocsd_ete_cfg &() const { return m_ete_cfg; }; +//! cast operator returning struct const pointer +//operator const ocsd_ete_cfg *() const { return &m_ete_cfg; }; + +// ete superset of etmv4 - move info to underlying structure. +void ETEConfig::copyV4() +{ +    // copy over 1:1 regs +    m_cfg.reg_idr0 = m_ete_cfg.reg_idr0; +    m_cfg.reg_idr1 = m_ete_cfg.reg_idr1; +    m_cfg.reg_idr2 = m_ete_cfg.reg_idr2; +    m_cfg.reg_idr8 = m_ete_cfg.reg_idr8; +    m_cfg.reg_idr9 = 0; +    m_cfg.reg_idr10 = 0; +    m_cfg.reg_idr11 = 0; +    m_cfg.reg_idr12 = 0; +    m_cfg.reg_idr13 = 0; +    m_cfg.reg_configr = m_ete_cfg.reg_configr; +    m_cfg.reg_traceidr = m_ete_cfg.reg_traceidr; +    m_cfg.core_prof = m_ete_cfg.core_prof; +    m_cfg.arch_ver = m_ete_cfg.arch_ver; + +    // override major / minor version as part of devarch +    m_MajVer = (uint8_t)((m_ete_cfg.reg_devarch & 0xF000) >> 12); +    m_MinVer = (uint8_t)((m_ete_cfg.reg_devarch & 0xF0000) >> 16); +} + +/* End of File trc_cmp_cfg_ete.cpp */ diff --git a/decoder/source/etmv3/trc_pkt_elem_etmv3.cpp b/decoder/source/etmv3/trc_pkt_elem_etmv3.cpp index f1e411f72423..74034c3c3e8f 100644 --- a/decoder/source/etmv3/trc_pkt_elem_etmv3.cpp +++ b/decoder/source/etmv3/trc_pkt_elem_etmv3.cpp @@ -659,7 +659,7 @@ void EtmV3TrcPacket::getExcepStr(std::string &excepStr) const          "IRQ4", "IRQ5", "IRQ6", "IRQ7",          "IRQ0","usage Fault","NMI","SVC",          "DebugMonitor", "Mem Manage","PendSV","SysTick", -        "Reserved","PE Reset","Reserved","HardFault" +        "Reserved","PE Reset","Reserved","HardFault",          "Reserved","BusFault","Reserved","Reserved"      }; diff --git a/decoder/source/etmv4/trc_cmp_cfg_etmv4.cpp b/decoder/source/etmv4/trc_cmp_cfg_etmv4.cpp index 9f5b37396b46..6f8bf790d293 100644 --- a/decoder/source/etmv4/trc_cmp_cfg_etmv4.cpp +++ b/decoder/source/etmv4/trc_cmp_cfg_etmv4.cpp @@ -98,7 +98,7 @@ void EtmV4Config::CalcVMIDSize()      uint32_t vmidszF = (m_cfg.reg_idr2 >> 10) & 0x1F;      if(vmidszF == 1)          m_VMIDSize = 8; -    else if(MinVersion() > 0) +    else if(FullVersion() > 0x40)      {          if(vmidszF == 2)              m_VMIDSize = 16; diff --git a/decoder/source/etmv4/trc_etmv4_stack_elem.cpp b/decoder/source/etmv4/trc_etmv4_stack_elem.cpp index 8e9ba9ac43ca..a5d889413eb2 100644 --- a/decoder/source/etmv4/trc_etmv4_stack_elem.cpp +++ b/decoder/source/etmv4/trc_etmv4_stack_elem.cpp @@ -128,6 +128,40 @@ TrcStackQElem *EtmV4P0Stack::createQElem(const ocsd_etmv4_i_pkt_type root_pkt, c      return pElem;  } +TrcStackElemMarker *EtmV4P0Stack::createMarkerElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const trace_marker_payload_t &marker) +{ +    TrcStackElemMarker *pElem = new (std::nothrow) TrcStackElemMarker(root_pkt, root_index); +    if (pElem) +    { +        pElem->setMarker(marker); +        push_front(pElem); +    } +    return pElem; +} + +TrcStackElemAddr *EtmV4P0Stack::createSrcAddrElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const etmv4_addr_val_t &addr_val) +{ +    TrcStackElemAddr *pElem = new (std::nothrow) TrcStackElemAddr(root_pkt, root_index, true); +    if (pElem) +    { +        pElem->setAddr(addr_val); +        push_front(pElem); +    } +    return pElem; +} + +TrcStackElemITE *EtmV4P0Stack::createITEElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const trace_sw_ite_t &ite) +{ +    TrcStackElemITE *pElem = new (std::nothrow) TrcStackElemITE(root_pkt, root_index); +    if (pElem) +    { +        pElem->setITE(ite); +        push_front(pElem); +    } +    return pElem; +} + +  // iteration functions  void EtmV4P0Stack::from_front_init()  { @@ -150,6 +184,10 @@ void EtmV4P0Stack::erase_curr_from_front()      erase_iter = m_iter;      erase_iter--;      m_P0_stack.erase(erase_iter); + +    // explicitly delete the item here as the caller can no longer reference it. +    // fixes memory leak from github issue #52 +    delete *erase_iter;  } diff --git a/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp b/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp index 393046ba23d1..89c45052868c 100644 --- a/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp +++ b/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp @@ -39,7 +39,8 @@  #define DCD_NAME "DCD_ETMV4" -static const uint32_t ETMV4_SUPPORTED_DECODE_OP_FLAGS = OCSD_OPFLG_PKTDEC_COMMON; +static const uint32_t ETMV4_SUPPORTED_DECODE_OP_FLAGS = OCSD_OPFLG_PKTDEC_COMMON | +                        ETE_OPFLG_PKTDEC_SRCADDR_N_ATOMS;  TrcPktDecodeEtmV4I::TrcPktDecodeEtmV4I()      : TrcPktDecodeBase(DCD_NAME) @@ -101,6 +102,14 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processPacket()                  m_curr_state = DECODE_PKTS;                  m_return_stack.flush();              } +            /* ETE spec allows early event packets. */ +            else if ((m_config->MajVersion() >= 0x5) &&  +                     (m_curr_packet_in->getType() == ETM4_PKT_I_EVENT)) +            { +                err = decodePacket(); +                if (err) +                    resp = OCSD_RESP_FATAL_INVALID_DATA; +            }              bPktDone = true;              break; @@ -261,6 +270,7 @@ void TrcPktDecodeEtmV4I::resetDecoder()      m_out_elem.resetElemStack();      m_last_IS = 0;      clearElemRes(); +    m_ete_first_ts_marker = false;      // elements associated with data trace  #ifdef DATA_TRACE_SUPPORTED @@ -358,7 +368,25 @@ ocsd_err_t TrcPktDecodeEtmV4I::decodePacket()              if (m_P0_stack.createAddrElem(m_curr_packet_in->getType(), m_index_curr_pkt, addr) == 0)                  bAllocErr = true; -            is_addr = true; +            is_addr = true;  // may be waiting for target address from indirect branch +        } +        break; + +    case ETE_PKT_I_SRC_ADDR_MATCH: +    case ETE_PKT_I_SRC_ADDR_S_IS0: +    case ETE_PKT_I_SRC_ADDR_S_IS1: +    case ETE_PKT_I_SRC_ADDR_L_32IS0: +    case ETE_PKT_I_SRC_ADDR_L_32IS1: +    case ETE_PKT_I_SRC_ADDR_L_64IS0: +    case ETE_PKT_I_SRC_ADDR_L_64IS1: +        { +            etmv4_addr_val_t addr; + +            addr.val = m_curr_packet_in->getAddrVal(); +            addr.isa = m_curr_packet_in->getAddrIS(); +            if (m_P0_stack.createSrcAddrElem(m_curr_packet_in->getType(), m_index_curr_pkt, addr) == 0) +                bAllocErr = true; +            m_curr_spec_depth++;          }          break; @@ -438,16 +466,26 @@ ocsd_err_t TrcPktDecodeEtmV4I::decodePacket()          }          break; +    case ETE_PKT_I_TS_MARKER: +        { +            trace_marker_payload_t marker; +            marker.type = ELEM_MARKER_TS; +            marker.value = 0; +            if (m_P0_stack.createMarkerElem(m_curr_packet_in->getType(), m_index_curr_pkt, marker) == 0) +                bAllocErr = true; +        } +        break; +      case ETM4_PKT_I_BAD_SEQUENCE: -        err = handleBadPacket("Bad byte sequence in packet."); +        err = handleBadPacket("Bad byte sequence in packet.", m_index_curr_pkt);          break;      case ETM4_PKT_I_BAD_TRACEMODE: -        err = handleBadPacket("Invalid packet type for trace mode."); +        err = handleBadPacket("Invalid packet type for trace mode.", m_index_curr_pkt);          break;      case ETM4_PKT_I_RESERVED: -        err = handleBadPacket("Reserved packet header"); +        err = handleBadPacket("Reserved packet header", m_index_curr_pkt);          break;      // speculation  @@ -502,8 +540,44 @@ ocsd_err_t TrcPktDecodeEtmV4I::decodePacket()          }          break; +        /* transactional memory packets */ +    case ETE_PKT_I_TRANS_ST: +        { +            if (m_P0_stack.createParamElemNoParam(P0_TRANS_START, m_config->commTransP0(), m_curr_packet_in->getType(), m_index_curr_pkt) == 0) +                bAllocErr = true; +            if (m_config->commTransP0()) +                m_curr_spec_depth++; +        } +        break; + +    case ETE_PKT_I_TRANS_COMMIT: +        { +            if (m_P0_stack.createParamElemNoParam(P0_TRANS_COMMIT, false, m_curr_packet_in->getType(), m_index_curr_pkt) == 0) +                bAllocErr = true; +        } +        break; + +    case ETE_PKT_I_TRANS_FAIL: +        { +            if (m_P0_stack.createParamElemNoParam(P0_TRANS_FAIL, false, m_curr_packet_in->getType(), m_index_curr_pkt) == 0) +                bAllocErr = true; +        } +        break; + +        /* PE Instrumentation packet */ +    case ETE_PKT_I_ITE: +        { +            trace_sw_ite_t ite_pkt; + +            ite_pkt.el = m_curr_packet_in->getITE_EL(); +            ite_pkt.value = m_curr_packet_in->getITE_value(); +            if (m_P0_stack.createITEElem(m_curr_packet_in->getType(), m_index_curr_pkt, ite_pkt) == 0) +                bAllocErr = true; +        } +        break; +      /*** presently unsupported packets ***/ -    /* conditional instruction tracing */ +        /* conditional instruction tracing */      case ETM4_PKT_I_COND_FLUSH:      case ETM4_PKT_I_COND_I_F1:      case ETM4_PKT_I_COND_I_F2: @@ -525,14 +599,16 @@ ocsd_err_t TrcPktDecodeEtmV4I::decodePacket()          //resp = OCSD_RESP_FATAL_INVALID_DATA;  #endif          err = OCSD_ERR_UNSUPP_DECODE_PKT; -        LogError(ocsdError(sev, err, "Data trace releated, unsupported packet type.")); +        if (sev == OCSD_ERR_SEV_WARN) +                        LogError(ocsdError(sev, err, "Data trace related, unsupported packet type.")); +        else  +            err = handlePacketSeqErr(err, m_index_curr_pkt, "Data trace related, unsupported packet type.");          }          break;      default:          // any other packet - bad packet error -        err = OCSD_ERR_BAD_DECODE_PKT; -        LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,"Unknown packet type.")); +        err = handleBadPacket("Unknown packet type.", m_index_curr_pkt);          break;      } @@ -566,6 +642,9 @@ void TrcPktDecodeEtmV4I::doTraceInfoPacket()      m_trace_info = m_curr_packet_in->getTraceInfo();      m_cc_threshold = m_curr_packet_in->getCCThreshold();      m_curr_spec_depth = m_curr_packet_in->getCurrSpecDepth(); +    /* put a trans marker in stack if started in trans state */ +    if (m_trace_info.bits.in_trans_state) +        m_P0_stack.createParamElemNoParam(P0_TRANS_TRACE_INIT, false, m_curr_packet_in->getType(), m_index_curr_pkt);      // elements associated with data trace  #ifdef DATA_TRACE_SUPPORTED @@ -592,14 +671,18 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV4I::resolveElements()              if (m_elem_res.P0_commit)                  err = commitElements(); -            if (!err && m_elem_res.P0_cancel) -                err = cancelElements(); +            // allow for early flush on context element  +            if (!m_elem_res.P0_commit) { -            if (!err && m_elem_res.mispredict) -                err = mispredictAtom(); -             -            if (!err && m_elem_res.discard) -                err = discardElements(); +                if (!err && m_elem_res.P0_cancel) +                    err = cancelElements(); + +                if (!err && m_elem_res.mispredict) +                    err = mispredictAtom(); + +                if (!err && m_elem_res.discard) +                    err = discardElements(); +            }              if (err != OCSD_OK)                  resp = OCSD_RESP_FATAL_INVALID_DATA; @@ -634,10 +717,11 @@ ocsd_err_t TrcPktDecodeEtmV4I::commitElements()      int num_commit_req = m_elem_res.P0_commit;      ocsd_trc_index_t err_idx = 0;      TrcStackElem *pElem = 0;    // stacked element pointer +    bool contextFlush = false;      err = m_out_elem.resetElemStack(); -    while(m_elem_res.P0_commit && !err) +    while(m_elem_res.P0_commit && !err && !contextFlush)      {          if (m_P0_stack.size() > 0)          { @@ -646,7 +730,7 @@ ocsd_err_t TrcPktDecodeEtmV4I::commitElements()              switch (pElem->getP0Type())              { -            // indicates a trace restart - beginning of trace or discontinuiuty +                // indicates a trace restart - beginning of trace or discontinuiuty              case P0_TRC_ON:                  err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_TRACE_ON);                  if (!err) @@ -661,7 +745,7 @@ ocsd_err_t TrcPktDecodeEtmV4I::commitElements()                  {                  TrcStackElemAddr *pAddrElem = dynamic_cast<TrcStackElemAddr *>(pElem);                  m_return_stack.clear_pop_pending(); // address removes the need to pop the indirect address target from the stack -                if(pAddrElem) +                if (pAddrElem)                  {                      SetInstrInfoInAddrISA(pAddrElem->getAddr().val, pAddrElem->getAddr().isa);                      m_need_addr = false; @@ -672,15 +756,24 @@ ocsd_err_t TrcPktDecodeEtmV4I::commitElements()              case P0_CTXT:                  {                  TrcStackElemCtxt *pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem); -                if(pCtxtElem) +                if (pCtxtElem)                  {                      etmv4_context_t ctxt = pCtxtElem->getContext();                      // check this is an updated context                      if(ctxt.updated)                      {                                                  err = m_out_elem.addElem(pElem->getRootIndex()); -                        if (!err) +                        if (!err) {                              updateContext(pCtxtElem, outElem()); + +                            // updated context - need to force this to be output to the client so correct memory  +                            // context can be used. +                            contextFlush = true; +                             +                            // invalidate memory accessor cacheing - force next memory access out to client to  +                            // ensure that the correct memory context is in play when decoding subsequent atoms. +                            invalidateMemAccCache(); +                        }                      }                  }                  } @@ -693,11 +786,15 @@ ocsd_err_t TrcPktDecodeEtmV4I::commitElements()                  err = processTS_CC_EventElem(pElem);                  break; +            case P0_MARKER: +                err = processMarkerElem(pElem); +                break; +              case P0_ATOM:                  {                  TrcStackElemAtom *pAtomElem = dynamic_cast<TrcStackElemAtom *>(pElem); -                if(pAtomElem) +                if (pAtomElem)                  {                      while(!pAtomElem->isEmpty() && m_elem_res.P0_commit && !err)                      { @@ -709,13 +806,13 @@ ocsd_err_t TrcPktDecodeEtmV4I::commitElements()                          // if address and context do instruction trace follower.                          // otherwise skip atom and reduce committed elements -                        if(!m_need_ctxt && !m_need_addr) +                        if (!m_need_ctxt && !m_need_addr)                          {                              err = processAtom(atom);                          }                          m_elem_res.P0_commit--; // mark committed                       } -                    if(!pAtomElem->isEmpty())    +                    if (!pAtomElem->isEmpty())                          bPopElem = false;   // don't remove if still atoms to process.                  }                  } @@ -746,9 +843,27 @@ ocsd_err_t TrcPktDecodeEtmV4I::commitElements()                      m_elem_res.P0_commit--;                  break; +            case P0_SRC_ADDR: +                err = processSourceAddress(); +                m_elem_res.P0_commit--; +                break; +              case P0_Q:                  err = processQElement();                  m_elem_res.P0_commit--; +				break; + +            case P0_TRANS_START: +                if (m_config->commTransP0()) +                    m_elem_res.P0_commit--; +            case P0_TRANS_COMMIT: +            case P0_TRANS_FAIL: +            case P0_TRANS_TRACE_INIT: +                err = processTransElem(pElem); +                break; + +            case P0_ITE: +                err = processITEElem(pElem);                  break;              } @@ -757,9 +872,8 @@ ocsd_err_t TrcPktDecodeEtmV4I::commitElements()          }          else          { -            // too few elements for commit operation - decode error. -            err = OCSD_ERR_COMMIT_PKT_OVERRUN; -            LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_COMMIT_PKT_OVERRUN,err_idx,m_CSID,"Not enough elements to commit")); +            // too few elements for commit operation - decode error.             +            err = handlePacketSeqErr(OCSD_ERR_COMMIT_PKT_OVERRUN, err_idx, "Not enough elements to commit");          }      } @@ -779,7 +893,7 @@ ocsd_err_t TrcPktDecodeEtmV4I::returnStackPop()          if (m_return_stack.overflow())          {              err = OCSD_ERR_RET_STACK_OVERFLOW; -            LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, "Trace Return Stack Overflow.")); +            err = handlePacketSeqErr(err, OCSD_BAD_TRC_INDEX, "Trace Return Stack Overflow.");          }          else          { @@ -824,6 +938,25 @@ ocsd_err_t TrcPktDecodeEtmV4I::commitElemOnEOT()          case P0_CTXT:              break; +            // trans +            // P0 trans - clear and stop, otherwise skip +        case P0_TRANS_START: +            if (m_config->commTransP0()) +                m_P0_stack.delete_all(); +            break; + +            // non-speculative trans fail / commit - could appear at EoT after valid trace +            // but without a subsequent P0 that would force output. +        case P0_TRANS_FAIL: +        case P0_TRANS_COMMIT: +            if (m_max_spec_depth == 0 || m_curr_spec_depth == 0) +                err = processTransElem(pElem); +            break; + +            // others - skip non P0 +        case P0_TRANS_TRACE_INIT: +            break; +              // output          case P0_EVENT:          case P0_TS: @@ -831,6 +964,14 @@ ocsd_err_t TrcPktDecodeEtmV4I::commitElemOnEOT()          case P0_TS_CC:              err = processTS_CC_EventElem(pElem);              break; + +        case P0_MARKER: +            err = processMarkerElem(pElem); +            break; + +        case P0_ITE: +            err = processITEElem(pElem); +            break;          }          m_P0_stack.delete_back();      } @@ -886,6 +1027,8 @@ ocsd_err_t TrcPktDecodeEtmV4I::cancelElements()                      case P0_TS:                      case P0_CC:                      case P0_TS_CC: +                    case P0_MARKER: +                    case P0_ITE:                          m_P0_stack.pop_front(false);                          temp.push_back(pElem);                          break; @@ -895,6 +1038,8 @@ ocsd_err_t TrcPktDecodeEtmV4I::cancelElements()                          break;                      }                  } +                if (m_P0_stack.size() == 0) +                    P0StackDone = true;              }          }          // may have some unseen elements @@ -908,21 +1053,23 @@ ocsd_err_t TrcPktDecodeEtmV4I::cancelElements()          {              // too few elements for commit operation - decode error.              err = OCSD_ERR_COMMIT_PKT_OVERRUN; -            LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, m_index_curr_pkt, m_CSID, "Not enough elements to cancel")); +            err = handlePacketSeqErr(err, m_index_curr_pkt, "Not enough elements to cancel");              m_elem_res.P0_cancel = 0;              break;          } -        -        if (temp.size()) +    } + +    /* restore any saved elements that are unaffected by cancel. */ +    if (temp.size()) +    { +        while (temp.size())          { -            while (temp.size()) -            { -                pElem = temp.back(); -                m_P0_stack.push_front(pElem); -                temp.pop_back(false); -            } +            pElem = temp.back(); +            m_P0_stack.push_front(pElem); +            temp.pop_back(false);          }      } +      m_curr_spec_depth -= num_cancel_req - m_elem_res.P0_cancel;      return err;  } @@ -964,7 +1111,8 @@ ocsd_err_t TrcPktDecodeEtmV4I::mispredictAtom()      if (!bFoundAtom && !m_unseen_spec_elem)      {          err = OCSD_ERR_COMMIT_PKT_OVERRUN; -        LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, m_index_curr_pkt, m_CSID, "Not found mispredict atom")); +        err = handlePacketSeqErr(err, m_index_curr_pkt, "Not found mispredict atom");             +        //LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, m_index_curr_pkt, m_CSID, "Not found mispredict atom"));      }      m_elem_res.mispredict = false;      return err; @@ -980,7 +1128,12 @@ ocsd_err_t TrcPktDecodeEtmV4I::discardElements()      while ((m_P0_stack.size() > 0) && !err)      {          pElem = m_P0_stack.back(); -        err = processTS_CC_EventElem(pElem); +        if (pElem->getP0Type() == P0_MARKER) +            err = processMarkerElem(pElem); +        else if (pElem->getP0Type() == P0_MARKER) +            err = processITEElem(pElem); +        else +            err = processTS_CC_EventElem(pElem);          m_P0_stack.delete_back();      } @@ -1002,6 +1155,8 @@ ocsd_err_t TrcPktDecodeEtmV4I::discardElements()  ocsd_err_t TrcPktDecodeEtmV4I::processTS_CC_EventElem(TrcStackElem *pElem)  {      ocsd_err_t err = OCSD_OK; +    // ignore ts for ETE if not seen first TS marker on systems that use this. +    bool bPermitTS = !m_config->eteHasTSMarker() || m_ete_first_ts_marker;      switch (pElem->getP0Type())      { @@ -1016,7 +1171,7 @@ ocsd_err_t TrcPktDecodeEtmV4I::processTS_CC_EventElem(TrcStackElem *pElem)          case P0_TS:          {              TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem); -            if (pParamElem) +            if (pParamElem && bPermitTS)                  err = addElemTS(pParamElem, false);          }          break; @@ -1032,7 +1187,7 @@ ocsd_err_t TrcPktDecodeEtmV4I::processTS_CC_EventElem(TrcStackElem *pElem)          case P0_TS_CC:          {              TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem); -            if (pParamElem) +            if (pParamElem && bPermitTS)                  err = addElemTS(pParamElem, true);          }          break; @@ -1041,6 +1196,46 @@ ocsd_err_t TrcPktDecodeEtmV4I::processTS_CC_EventElem(TrcStackElem *pElem)  } +ocsd_err_t TrcPktDecodeEtmV4I::processMarkerElem(TrcStackElem *pElem) +{ +    ocsd_err_t err = OCSD_OK; +    TrcStackElemMarker *pMarkerElem = dynamic_cast<TrcStackElemMarker *>(pElem); + +    if (m_config->eteHasTSMarker() && (pMarkerElem->getMarker().type == ELEM_MARKER_TS)) +        m_ete_first_ts_marker = true; + +    if (!err) +    { +        err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_SYNC_MARKER); +        if (!err) +            m_out_elem.getCurrElem().setSyncMarker(pMarkerElem->getMarker()); +    } +    return err; +} + +ocsd_err_t TrcPktDecodeEtmV4I::processTransElem(TrcStackElem *pElem) +{ +    ocsd_err_t err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_MEMTRANS); +    if (!err) +    { +        outElem().setTransactionType((trace_memtrans_t)((int)OCSD_MEM_TRANS_FAIL - +            ((int)P0_TRANS_FAIL - (int)pElem->getP0Type()))); +    } +    return err; +} + +ocsd_err_t TrcPktDecodeEtmV4I::processITEElem(TrcStackElem *pElem) +{ +    ocsd_err_t err = OCSD_OK; +    TrcStackElemITE *pITEElem = dynamic_cast<TrcStackElemITE *>(pElem); + +    err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_INSTRUMENTATION); +    if (!err) { +        outElem().setITEInfo(pITEElem->getITE()); +    } +    return err; +} +  ocsd_err_t TrcPktDecodeEtmV4I::addElemCC(TrcStackElemParam *pParamElem)  {      ocsd_err_t err = OCSD_OK; @@ -1078,16 +1273,22 @@ ocsd_err_t TrcPktDecodeEtmV4I::addElemEvent(TrcStackElemParam *pParamElem)      return err;  } -void TrcPktDecodeEtmV4I::setElemTraceRange(OcsdTraceElement &elemIn, const instr_range_t &addr_range,  -                                           const bool executed, ocsd_trc_index_t index) +void TrcPktDecodeEtmV4I::setElemTraceRange(OcsdTraceElement &elemIn, const instr_range_t &addr_range, +    const bool executed, ocsd_trc_index_t index) +{ +    setElemTraceRangeInstr(elemIn, addr_range, executed, index, m_instr_info); +} + +void TrcPktDecodeEtmV4I::setElemTraceRangeInstr(OcsdTraceElement &elemIn, const instr_range_t &addr_range, +    const bool executed, ocsd_trc_index_t index, ocsd_instr_info &instr)  {      elemIn.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE); -    elemIn.setLastInstrInfo(executed, m_instr_info.type, m_instr_info.sub_type, m_instr_info.instr_size); -    elemIn.setISA(m_instr_info.isa); -    elemIn.setLastInstrCond(m_instr_info.is_conditional); +    elemIn.setLastInstrInfo(executed, instr.type, instr.sub_type, instr.instr_size); +    elemIn.setISA(instr.isa); +    elemIn.setLastInstrCond(instr.is_conditional);      elemIn.setAddrRange(addr_range.st_addr, addr_range.en_addr, addr_range.num_instr);      if (executed) -        m_instr_info.isa = m_instr_info.next_isa; +        instr.isa = instr.next_isa;  }  ocsd_err_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom) @@ -1096,6 +1297,7 @@ ocsd_err_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom)      TrcStackElem *pElem = m_P0_stack.back();  // get the atom element      WP_res_t WPRes;      instr_range_t addr_range; +    bool ETE_ERET = false;      // new element for this processed atom      if ((err = m_out_elem.addElem(pElem->getRootIndex())) != OCSD_OK) @@ -1114,7 +1316,8 @@ ocsd_err_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom)          }          else          { -            LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,pElem->getRootIndex(),m_CSID,"Error processing atom packet."));   +            err = handlePacketSeqErr(err, pElem->getRootIndex(), "Error processing atom packet."); +            //LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,pElem->getRootIndex(),m_CSID,"Error processing atom packet."));                return err;          }      } @@ -1144,10 +1347,22 @@ ocsd_err_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom)                  if (m_instr_info.is_link)                      m_return_stack.push(nextAddr,m_instr_info.isa);                  m_return_stack.set_pop_pending();  // need to know next packet before we know what is to happen + +                /* ETE does not have ERET trace packets - however to maintain the illusion if we see an ERET +                   output a gen elem ERET packet */ +                if (isETEConfig() && (m_instr_info.sub_type == OCSD_S_INSTR_V8_ERET)) +                    ETE_ERET = true;              }              break;          }          setElemTraceRange(outElem(), addr_range, (atom == ATOM_E), pElem->getRootIndex()); + +        if (ETE_ERET) +        { +            err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_EXCEPTION_RET); +            if (err) +                return err; +        }      }      else      { @@ -1182,55 +1397,64 @@ ocsd_err_t TrcPktDecodeEtmV4I::processException()      TrcStackElemAddr *pAddressElem = 0;      TrcStackElemCtxt *pCtxtElem = 0;      bool branch_target = false;    // exception address implies prior branch target address -    ocsd_vaddr_t excep_ret_addr; +    ocsd_vaddr_t excep_ret_addr = 0;      ocsd_trc_index_t excep_pkt_index;      WP_res_t WPRes = WP_NOT_FOUND; +    bool ETE_resetPkt = false;      // grab the exception element off the stack      pExceptElem = dynamic_cast<TrcStackElemExcept *>(m_P0_stack.back());  // get the exception element      excep_pkt_index = pExceptElem->getRootIndex();      branch_target = pExceptElem->getPrevSame(); +    if (pExceptElem->getRootPkt() == ETE_PKT_I_PE_RESET) +        ETE_resetPkt = true;      m_P0_stack.pop_back(); // remove the exception element -    pElem = m_P0_stack.back();  // look at next element. -    if(pElem->getP0Type() == P0_CTXT) +    // ETE reset has no follow up address, the rest of the exceptions do.... +    if (!ETE_resetPkt)       { -        pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem); -        m_P0_stack.pop_back(); // remove the context element -        pElem = m_P0_stack.back();  // next one should be an address element -    } -    -   if(pElem->getP0Type() != P0_ADDR) -   { -       // no following address element - indicate processing error.       -       LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ, excep_pkt_index,m_CSID,"Address missing in exception packet.")); -       return OCSD_ERR_BAD_PACKET_SEQ; -   } -   else -   { -        // extract address -        pAddressElem = static_cast<TrcStackElemAddr *>(pElem); -        excep_ret_addr = pAddressElem->getAddr().val; - -        // see if there is an address + optional context element implied  -        // prior to the exception. -        if (branch_target) +        pElem = m_P0_stack.back();  // look at next element. +        if (pElem->getP0Type() == P0_CTXT)          { -            // this was a branch target address - update current setting -            bool b64bit = m_instr_info.isa == ocsd_isa_aarch64; -            if (pCtxtElem) { -                b64bit = pCtxtElem->getContext().SF; -            } +            pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem); +            m_P0_stack.pop_back(); // remove the context element +            pElem = m_P0_stack.back();  // next one should be an address element +        } -            // as the exception address was also a branch target address then update the  -            // current maintained address value. This also means that there is no range to -            // output before the exception packet. -            m_instr_info.instr_addr = excep_ret_addr;  -            m_instr_info.isa = (pAddressElem->getAddr().isa == 0) ? +        if (pElem->getP0Type() != P0_ADDR) +        { +            // no following address element - indicate processing error. +             +            err = handlePacketSeqErr(OCSD_ERR_BAD_PACKET_SEQ, m_index_curr_pkt, "Address missing in exception packet.");       +            //LogError(ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_BAD_PACKET_SEQ, excep_pkt_index, m_CSID, "Address missing in exception packet.")); +            return err; +        } +        else +        { +            // extract address +            pAddressElem = static_cast<TrcStackElemAddr *>(pElem); +            excep_ret_addr = pAddressElem->getAddr().val; + +            // see if there is an address + optional context element implied  +            // prior to the exception. +            if (branch_target) +            { +                // this was a branch target address - update current setting +                bool b64bit = m_instr_info.isa == ocsd_isa_aarch64; +                if (pCtxtElem) { +                    b64bit = pCtxtElem->getContext().SF; +                } + +                // as the exception address was also a branch target address then update the  +                // current maintained address value. This also means that there is no range to +                // output before the exception packet. +                m_instr_info.instr_addr = excep_ret_addr; +                m_instr_info.isa = (pAddressElem->getAddr().isa == 0) ?                      (b64bit ? ocsd_isa_aarch64 : ocsd_isa_arm) : ocsd_isa_thumb2; -            m_need_addr = false; +                m_need_addr = false; +            }          } -    }    +    }      // need to output something - set up an element      if ((err = m_out_elem.addElem(excep_pkt_index))) @@ -1246,69 +1470,72 @@ ocsd_err_t TrcPktDecodeEtmV4I::processException()              return err;      } -    // if the preferred return address is not the end of the last output range... -    if (m_instr_info.instr_addr != excep_ret_addr) -    {         -        bool range_out = false; -        instr_range_t addr_range; +    if (!ETE_resetPkt) +    { +        // if the preferred return address is not the end of the last output range... +        if (m_instr_info.instr_addr != excep_ret_addr) +        { +            bool range_out = false; +            instr_range_t addr_range; -        // look for match to return address. -        err = traceInstrToWP(addr_range, WPRes, true, excep_ret_addr); +            // look for match to return address. +            err = traceInstrToWP(addr_range, WPRes, true, excep_ret_addr); -        if(err != OCSD_OK) -        { -            if(err == OCSD_ERR_UNSUPPORTED_ISA) +            if (err != OCSD_OK)              { -                m_need_addr = true; -                m_need_ctxt = true; -                LogError(ocsdError(OCSD_ERR_SEV_WARN,err, excep_pkt_index,m_CSID,"Warning: unsupported instruction set processing exception packet.")); +                if (err == OCSD_ERR_UNSUPPORTED_ISA) +                { +                    m_need_addr = true; +                    m_need_ctxt = true; +                    LogError(ocsdError(OCSD_ERR_SEV_WARN, err, excep_pkt_index, m_CSID, "Warning: unsupported instruction set processing exception packet.")); +                } +                else +                { +                    LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, excep_pkt_index, m_CSID, "Error processing exception packet.")); +                } +                return err; +            } + +            if (WPFound(WPRes)) +            { +                // waypoint address found - output range +                setElemTraceRange(outElem(), addr_range, true, excep_pkt_index); +                range_out = true;              }              else              { -                LogError(ocsdError(OCSD_ERR_SEV_ERROR,err, excep_pkt_index,m_CSID,"Error processing exception packet.")); +                // no waypoint - likely inaccessible memory range. +                m_need_addr = true; // need an address update  + +                if (addr_range.st_addr != addr_range.en_addr) +                { +                    // some trace before we were out of memory access range +                    setElemTraceRange(outElem(), addr_range, true, excep_pkt_index); +                    range_out = true; +                }              } -            return err; -        } -        if(WPFound(WPRes)) -        { -            // waypoint address found - output range -            setElemTraceRange(outElem(), addr_range, true, excep_pkt_index); -            range_out = true; -        } -        else -        { -            // no waypoint - likely inaccessible memory range. -            m_need_addr = true; // need an address update  -             -            if(addr_range.st_addr != addr_range.en_addr) +            // used the element need another for NACC or EXCEP. +            if (range_out)              { -                // some trace before we were out of memory access range -                setElemTraceRange(outElem(), addr_range, true, excep_pkt_index); -                range_out = true; +                if ((err = m_out_elem.addElem(excep_pkt_index))) +                    return err;              }          } -        // used the element need another for NACC or EXCEP. -        if (range_out) +        // watchpoint walk resulted in inaccessible memory call... +        if (WPNacc(WPRes))          { + +            outElem().setType(OCSD_GEN_TRC_ELEM_ADDR_NACC); +            outElem().st_addr = m_instr_info.instr_addr; + +            // used the element - need another for the final exception packet.              if ((err = m_out_elem.addElem(excep_pkt_index)))                  return err;          }      } -    -    // watchpoint walk resulted in inaccessible memory call... -    if (WPNacc(WPRes)) -    { -         -        outElem().setType(OCSD_GEN_TRC_ELEM_ADDR_NACC); -        outElem().st_addr = m_instr_info.instr_addr; -        // used the element - need another for the final exception packet. -        if ((err = m_out_elem.addElem(excep_pkt_index))) -            return err; -    } -          // output exception element.      outElem().setType(OCSD_GEN_TRC_ELEM_EXCEPTION); @@ -1453,6 +1680,163 @@ ocsd_err_t TrcPktDecodeEtmV4I::processQElement()      return err;  } +ocsd_err_t TrcPktDecodeEtmV4I::processSourceAddress() +{ +    ocsd_err_t err = OCSD_OK; +    TrcStackElemAddr *pElem = dynamic_cast<TrcStackElemAddr *>(m_P0_stack.back());  // get the address element +    etmv4_addr_val_t srcAddr = pElem->getAddr(); +    uint32_t opcode, bytesReq = 4; +    ocsd_vaddr_t currAddr = m_instr_info.instr_addr;    // get the latest decoded address. +    instr_range_t out_range; +    bool bSplitRangeOnN = getComponentOpMode() & ETE_OPFLG_PKTDEC_SRCADDR_N_ATOMS ? true : false; + +    // check we can read instruction @ source address +    err = accessMemory(srcAddr.val, getCurrMemSpace(), &bytesReq, (uint8_t *)&opcode); +    if (err != OCSD_OK) +    {         +        LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pElem->getRootIndex(), m_CSID, "Mem access error processing source address packet.")); +        return err; +    } + +    if (bytesReq != 4) +    { +        // can't access - no bytes returned - output nacc. +        err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_ADDR_NACC); +        outElem().setAddrStart(srcAddr.val); +        return err; +    } + +    // analyze opcode @ source address.  +    m_instr_info.opcode = opcode; +    m_instr_info.instr_addr = srcAddr.val; +    err = instrDecode(&m_instr_info); +    if (err != OCSD_OK) +    {         +        LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pElem->getRootIndex(), m_CSID, "Instruction decode error processing source address packet.")); +        return err; +    } +    m_instr_info.instr_addr += m_instr_info.instr_size; + +    // initial instruction count for the range. +    out_range.num_instr = 1; + +    // calculate range traced... +    if (m_need_addr || (currAddr > srcAddr.val)) +    { +        // we were waiting for a target address, or missing trace  +        // that indicates how we got to the source address. +        m_need_addr = false; +        out_range.st_addr = srcAddr.val; +    } +    else +        out_range.st_addr = currAddr; +    out_range.en_addr = m_instr_info.instr_addr; + +    // count instructions +    if (out_range.en_addr - out_range.st_addr > m_instr_info.instr_size) +    { +        if ((m_instr_info.isa != ocsd_isa_thumb2) && !bSplitRangeOnN) +        { +            // all 4 byte instructions - just calculate... +            out_range.num_instr = (uint32_t)(out_range.en_addr - out_range.st_addr) / 4; +        } +        else +        { +            // need to count T32 - 2 or 4 byte instructions or we are spotting N atoms +            ocsd_instr_info instr; // going back to start of range so make a copy of info. +            bool bMemAccErr = false; + +            instr.instr_addr = out_range.st_addr; +            instr.isa = m_instr_info.isa; +            instr.pe_type = m_instr_info.pe_type; +            instr.dsb_dmb_waypoints = m_instr_info.dsb_dmb_waypoints; +            instr.wfi_wfe_branch = m_instr_info.wfi_wfe_branch; +            out_range.num_instr = 0; + +            while ((instr.instr_addr < out_range.en_addr) && !bMemAccErr) +            { +                bytesReq = 4; +                err = accessMemory(instr.instr_addr, getCurrMemSpace(), &bytesReq, (uint8_t *)&opcode); +                if (err != OCSD_OK) +                { +                    LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pElem->getRootIndex(), m_CSID, "Mem access error processing source address packet.")); +                    return err; +                } + +                if (bytesReq == 4) +                { +                    instr.opcode = opcode; +                    err = instrDecode(&instr); +                    if (err != OCSD_OK) +                    { +                        LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pElem->getRootIndex(), m_CSID, "Instruction decode error processing source address packet.")); +                        return err; +                    } + +                    instr.instr_addr += instr.instr_size; +                    out_range.num_instr++; + +                    /* if we are doing N atom ranges ...*/ +                    if (bSplitRangeOnN && (instr.instr_addr < out_range.en_addr)) +                    { +                        if (instr.type != OCSD_INSTR_OTHER) +                        { +                            instr_range_t mid_range = out_range; +                            mid_range.en_addr = instr.instr_addr; + +                            err = m_out_elem.addElem(pElem->getRootIndex()); +                            if (err) +                                return err; +                            setElemTraceRangeInstr(outElem(), mid_range, false, pElem->getRootIndex(), instr); + +                            out_range.st_addr = mid_range.en_addr; +                            out_range.num_instr = 0; +                        } +                    } +                } +                else +                { +                    // something inaccessible between last and current... +                    bMemAccErr = true; + +                    err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_ADDR_NACC); +                    if (err) +                        return err; +                    outElem().setAddrStart(srcAddr.val); + +                    // force range to the one instruction +                    out_range.num_instr = 1; +                    out_range.st_addr = srcAddr.val; +                    out_range.en_addr = m_instr_info.instr_addr;  // instr after the decoded instruction @ srcAddr. +                } +            } +        } +    } + +    // got to the source address - output trace range, and instruction as E atom. +    switch (m_instr_info.type) +    { +    case OCSD_INSTR_BR: +        if (m_instr_info.is_link) +            m_return_stack.push(m_instr_info.instr_addr, m_instr_info.isa); +        m_instr_info.instr_addr = m_instr_info.branch_addr; +        break; + +    case OCSD_INSTR_BR_INDIRECT: +        m_need_addr = true; // indirect branch taken - need new address. +        if (m_instr_info.is_link) +            m_return_stack.push(m_instr_info.instr_addr, m_instr_info.isa); +        m_return_stack.set_pop_pending();  // need to know next packet before we know what is to happen +        break; +    } +    m_instr_info.isa = m_instr_info.next_isa; + +    // set the trace range element. +    m_out_elem.addElem(pElem->getRootIndex()); +    setElemTraceRange(outElem(), out_range, true, pElem->getRootIndex()); +    return err; +} +  void TrcPktDecodeEtmV4I::SetInstrInfoInAddrISA(const ocsd_vaddr_t addr_val, const uint8_t isa)  {      m_instr_info.instr_addr = addr_val; @@ -1518,7 +1902,10 @@ void TrcPktDecodeEtmV4I::updateContext(TrcStackElemCtxt *pCtxtElem, OcsdTraceEle      m_is_64bit = (ctxt.SF != 0);      elem.context.bits64 = ctxt.SF;      m_is_secure = (ctxt.NS == 0); -    elem.context.security_level = ctxt.NS ? ocsd_sec_nonsecure : ocsd_sec_secure; +    if (ctxt.NSE) +        elem.context.security_level = ctxt.NS ? ocsd_sec_realm : ocsd_sec_root; +    else +        elem.context.security_level = ctxt.NS ? ocsd_sec_nonsecure : ocsd_sec_secure;      elem.context.exception_level = (ocsd_ex_level)ctxt.EL;      elem.context.el_valid = 1;      if(ctxt.updated_c) @@ -1537,27 +1924,42 @@ void TrcPktDecodeEtmV4I::updateContext(TrcStackElemCtxt *pCtxtElem, OcsdTraceEle      m_need_ctxt = false;  } -ocsd_err_t TrcPktDecodeEtmV4I::handleBadPacket(const char *reason) +ocsd_err_t TrcPktDecodeEtmV4I::handleBadPacket(const char *reason, ocsd_trc_index_t index /* = OCSD_BAD_TRC_INDEX */)  { -    ocsd_err_t err = OCSD_OK; +    ocsd_err_severity_t sev = OCSD_ERR_SEV_WARN; +    if (getComponentOpMode() & OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS) +        sev = OCSD_ERR_SEV_ERROR; -    if(getComponentOpMode() & OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS) -    { -        // error out - stop decoding -        err = OCSD_ERR_BAD_DECODE_PKT; -        LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,reason)); -    } -    else +    return handlePacketErr(OCSD_ERR_BAD_DECODE_PKT, sev, index, reason); +} + +ocsd_err_t TrcPktDecodeEtmV4I::handlePacketSeqErr(ocsd_err_t err, ocsd_trc_index_t index, const char *reason) +{ +    return handlePacketErr(err, OCSD_ERR_SEV_ERROR, index, reason); +} + +ocsd_err_t TrcPktDecodeEtmV4I::handlePacketErr(ocsd_err_t err, ocsd_err_severity_t sev, ocsd_trc_index_t index, const char *reason) +{ +    bool resetOnBadPackets = true; + +    if(getComponentOpMode() & OCSD_OPFLG_PKTDEC_HALT_BAD_PKTS) +        resetOnBadPackets = false; + +    LogError(ocsdError(sev, err, index, getCoreSightTraceID(), reason)); + +    if (resetOnBadPackets)      { -        LogError(ocsdError(OCSD_ERR_SEV_WARN, OCSD_ERR_BAD_DECODE_PKT, reason));          // switch to unsync - clear decode state          resetDecoder();          m_curr_state = NO_SYNC;          m_unsync_eot_info = UNSYNC_BAD_PACKET; +        err = OCSD_OK;      }      return err; +  } +  inline ocsd_mem_space_acc_t TrcPktDecodeEtmV4I::getCurrMemSpace()  {      static ocsd_mem_space_acc_t SMemSpace[] = { diff --git a/decoder/source/etmv4/trc_pkt_elem_etmv4i.cpp b/decoder/source/etmv4/trc_pkt_elem_etmv4i.cpp index 853fde499a1b..825b5f79e41b 100644 --- a/decoder/source/etmv4/trc_pkt_elem_etmv4i.cpp +++ b/decoder/source/etmv4/trc_pkt_elem_etmv4i.cpp @@ -38,6 +38,7 @@  EtmV4ITrcPacket::EtmV4ITrcPacket()  { +    protocol_version = 0x42;    // min protocol version.  }  EtmV4ITrcPacket::~EtmV4ITrcPacket() @@ -101,6 +102,8 @@ void EtmV4ITrcPacket::toString(std::string &str) const          contextStr(ctxtStr);      case ETM4_PKT_I_ADDR_L_32IS0:      case ETM4_PKT_I_ADDR_L_32IS1: +    case ETE_PKT_I_SRC_ADDR_L_32IS0: +    case ETE_PKT_I_SRC_ADDR_L_32IS1:          trcPrintableElem::getValStr(valStr, (v_addr.size == VA_64BIT) ? 64 : 32, v_addr.valid_bits, v_addr.val, true, (v_addr.pkt_bits < 32) ? v_addr.pkt_bits : 0);          str += "; Addr=" + valStr + "; " + ctxtStr;          break; @@ -110,6 +113,8 @@ void EtmV4ITrcPacket::toString(std::string &str) const          contextStr(ctxtStr);      case ETM4_PKT_I_ADDR_L_64IS0:      case ETM4_PKT_I_ADDR_L_64IS1: +    case ETE_PKT_I_SRC_ADDR_L_64IS0: +    case ETE_PKT_I_SRC_ADDR_L_64IS1:          trcPrintableElem::getValStr(valStr, (v_addr.size == VA_64BIT) ? 64 : 32, v_addr.valid_bits, v_addr.val, true, (v_addr.pkt_bits < 64) ? v_addr.pkt_bits : 0);          str += "; Addr=" + valStr + "; " + ctxtStr;          break; @@ -121,11 +126,14 @@ void EtmV4ITrcPacket::toString(std::string &str) const      case ETM4_PKT_I_ADDR_S_IS0:      case ETM4_PKT_I_ADDR_S_IS1: +    case ETE_PKT_I_SRC_ADDR_S_IS0: +    case ETE_PKT_I_SRC_ADDR_S_IS1:          trcPrintableElem::getValStr(valStr, (v_addr.size == VA_64BIT) ? 64 : 32, v_addr.valid_bits, v_addr.val, true, v_addr.pkt_bits);          str += "; Addr=" + valStr;          break;      case ETM4_PKT_I_ADDR_MATCH: +    case ETE_PKT_I_SRC_ADDR_MATCH:          addrMatchIdx(valStr);          str += ", " + valStr;          trcPrintableElem::getValStr(valStr, (v_addr.size == VA_64BIT) ? 64 : 32, v_addr.valid_bits, v_addr.val, true); @@ -161,7 +169,10 @@ void EtmV4ITrcPacket::toString(std::string &str) const          {              std::ostringstream oss;              oss << "; INFO=" << std::hex << "0x" << trace_info.val; -            oss << " { CC." << std::dec << trace_info.bits.cc_enabled << " }"; +            oss << " { CC." << std::dec << trace_info.bits.cc_enabled; +            if (isETE()) +                oss << ", TSTATE." << std::dec << trace_info.bits.in_trans_state; +            oss << " }";              if (trace_info.bits.cc_enabled)                  oss << "; CC_THRESHOLD=" << std::hex << "0x" << cc_threshold;              str += oss.str(); @@ -264,6 +275,14 @@ void EtmV4ITrcPacket::toString(std::string &str) const              }          }          break; + +    case ETE_PKT_I_ITE: +        { +            std::ostringstream oss; +            oss << "; EL" << std::dec << (int)ite_pkt.el << "; Payload=0x" << std::hex << ite_pkt.value; +            str += oss.str(); +        } +        break;      }  }    @@ -349,6 +368,16 @@ const char *EtmV4ITrcPacket::packetTypeName(const ocsd_etmv4_i_pkt_type type, co          pName = "I_EXCEPT_RTN";          pDesc = "Exception Return.";          break; +     +    case ETE_PKT_I_TRANS_ST: +        pName = "I_TRANS_ST"; +        pDesc = "Transaction Start."; +        break; + +    case ETE_PKT_I_TRANS_COMMIT: +        pName = "I_TRANS_COMMIT"; +        pDesc = "Transaction Commit."; +        break;      case ETM4_PKT_I_CCNT_F1:          pName = "I_CCNT_F1"; @@ -481,6 +510,11 @@ const char *EtmV4ITrcPacket::packetTypeName(const ocsd_etmv4_i_pkt_type type, co          pDesc = "Address & Context, Long, 64 bit, IS1.";          break; +    case ETE_PKT_I_TS_MARKER: +        pName = "I_TS_MARKER"; +        pDesc = "Timestamp Marker"; +        break; +      case ETM4_PKT_I_ADDR_MATCH:          pName = "I_ADDR_MATCH";          pDesc = "Exact Address Match."; @@ -521,6 +555,41 @@ const char *EtmV4ITrcPacket::packetTypeName(const ocsd_etmv4_i_pkt_type type, co          pDesc = "Q Packet.";          break; +    case ETE_PKT_I_SRC_ADDR_MATCH: +        pName = "I_SRC_ADDR_MATCH"; +        pDesc = "Exact Source Address Match."; +        break; + +    case ETE_PKT_I_SRC_ADDR_S_IS0: +        pName = "I_SRC_ADDR_S_IS0"; +        pDesc = "Source Address, Short, IS0."; +        break; + +    case ETE_PKT_I_SRC_ADDR_S_IS1: +        pName = "I_SRC_ADDR_S_IS1"; +        pDesc = "Source Address, Short, IS1."; +        break; + +    case ETE_PKT_I_SRC_ADDR_L_32IS0: +        pName = "I_SCR_ADDR_L_32IS0"; +        pDesc = "Source Address, Long, 32 bit, IS0."; +        break; + +    case ETE_PKT_I_SRC_ADDR_L_32IS1: +        pName = "I_SRC_ADDR_L_32IS1"; +        pDesc = "Source Address, Long, 32 bit, IS1."; +        break; + +    case ETE_PKT_I_SRC_ADDR_L_64IS0: +        pName = "I_SRC_ADDR_L_64IS0"; +        pDesc = "Source Address, Long, 64 bit, IS0."; +        break; + +    case ETE_PKT_I_SRC_ADDR_L_64IS1: +        pName = "I_SRC_ADDR_L_64IS1"; +        pDesc = "Source Address, Long, 64 bit, IS1."; +        break; +      case ETM4_PKT_I_ATOM_F6:          pName = "I_ATOM_F6";          pDesc = "Atom format 6."; @@ -566,6 +635,21 @@ const char *EtmV4ITrcPacket::packetTypeName(const ocsd_etmv4_i_pkt_type type, co          pDesc = "Overflow.";          break; +    case ETE_PKT_I_PE_RESET: +        pName = "I_PE_RESET"; +        pDesc = "PE Reset."; +        break; + +    case ETE_PKT_I_TRANS_FAIL: +        pName = "I_TRANS_FAIL"; +        pDesc = "Transaction Fail."; +        break; + +    case ETE_PKT_I_ITE: +        pName = "I_ITE"; +        pDesc = "Instrumentation"; +        break; +      default:          break;      } diff --git a/decoder/source/etmv4/trc_pkt_proc_etmv4i.cpp b/decoder/source/etmv4/trc_pkt_proc_etmv4i.cpp index d8c7d84667d1..d767bdc85643 100644 --- a/decoder/source/etmv4/trc_pkt_proc_etmv4i.cpp +++ b/decoder/source/etmv4/trc_pkt_proc_etmv4i.cpp @@ -45,6 +45,9 @@  static const uint32_t ETMV4_SUPPORTED_OP_FLAGS = OCSD_OPFLG_PKTPROC_COMMON; +// test defines - if testing with ETMv4 sources, disable error on ERET. +// #define ETE_TRACE_ERET_AS_IGNORE +  /* trace etmv4 packet processing class */  TrcPktProcEtmV4I::TrcPktProcEtmV4I() : TrcPktProcBase(ETMV4I_PKTS_NAME),      m_isInit(false), @@ -70,7 +73,9 @@ ocsd_err_t TrcPktProcEtmV4I::onProtocolConfig()      InitProcessorState();      m_config = *TrcPktProcBase::getProtocolConfig();      BuildIPacketTable();    // packet table based on config +    m_curr_packet.setProtocolVersion(m_config.FullVersion());      m_isInit = true; +    statsInit();      return OCSD_OK;  } @@ -152,6 +157,10 @@ ocsd_datapath_resp_t TrcPktProcEtmV4I::processData(  const ocsd_trc_index_t inde                  (err.getErrorCode() == OCSD_ERR_INVALID_PCKT_HDR))              {                  // send invalid packets up the pipe to let the next stage decide what to do. +                if (err.getErrorCode() == OCSD_ERR_INVALID_PCKT_HDR) +                    statsAddBadHdrCount(1); +                else +                    statsAddBadSeqCount(1);                  m_process_state = SEND_PKT;                   done = false;              } @@ -171,6 +180,7 @@ ocsd_datapath_resp_t TrcPktProcEtmV4I::processData(  const ocsd_trc_index_t inde          }      } while (!done); +    statsAddTotalCount(m_trcIn.processed());      *numBytesProcessed = m_trcIn.processed();      return resp;  } @@ -241,8 +251,8 @@ ocsd_datapath_resp_t TrcPktProcEtmV4I::outputUnsyncedRawPacket()  {      ocsd_datapath_resp_t resp = OCSD_RESP_CONT; - -   outputRawPacketToMonitor(m_packet_index,&m_curr_packet,m_dump_unsynced_bytes,&m_currPacketData[0]); +    statsAddUnsyncCount(m_dump_unsynced_bytes); +    outputRawPacketToMonitor(m_packet_index,&m_curr_packet,m_dump_unsynced_bytes,&m_currPacketData[0]);      if(!m_sent_notsync_packet)      {         @@ -290,6 +300,7 @@ void TrcPktProcEtmV4I::iPktNoPayload(const uint8_t lastByte)      switch(m_curr_packet.type)      {      case ETM4_PKT_I_ADDR_MATCH: +    case ETE_PKT_I_SRC_ADDR_MATCH:          m_curr_packet.setAddressExactMatch(lastByte & 0x3);          break; @@ -307,6 +318,8 @@ void TrcPktProcEtmV4I::iPktNoPayload(const uint8_t lastByte)      case ETM4_PKT_I_EXCEPT_RTN:      case ETM4_PKT_I_TRACE_ON:      case ETM4_PKT_I_FUNC_RET: +    case ETE_PKT_I_TRANS_ST: +    case ETE_PKT_I_TRANS_COMMIT:      case ETM4_PKT_I_IGNORE:      default: break;      } @@ -437,6 +450,8 @@ void TrcPktProcEtmV4I::iPktTraceInfo(const uint8_t lastByte)              m_tinfo_sections.sectFlags |= (lastByte & 0x80) ? 0 : TINFO_SPEC_SECT;          else if(!(m_tinfo_sections.sectFlags & TINFO_CYCT_SECT))              m_tinfo_sections.sectFlags |= (lastByte & 0x80) ? 0 : TINFO_CYCT_SECT; +        else if (!(m_tinfo_sections.sectFlags & TINFO_WNDW_SECT)) +            m_tinfo_sections.sectFlags |= (lastByte & 0x80) ? 0 : TINFO_WNDW_SECT;      }      // all sections accounted for? @@ -469,6 +484,11 @@ void TrcPktProcEtmV4I::iPktTraceInfo(const uint8_t lastByte)              idx += extractContField(m_currPacketData,idx,fieldVal);              m_curr_packet.setTraceInfoCyct(fieldVal);          } +        if ((presSect & TINFO_WNDW_SECT) && (idx < m_currPacketData.size())) +        { +            idx += extractContField(m_currPacketData, idx, fieldVal); +            /* Trace commit window unsupported in current ETE versions */ +        }          m_process_state = SEND_PKT;          m_first_trace_info = true;      } @@ -502,8 +522,11 @@ void TrcPktProcEtmV4I::iPktTimestamp(const uint8_t lastByte)      {                  int idx = 1;          uint64_t tsVal; -        int ts_bytes = extractContField64(m_currPacketData, idx, tsVal); -        int ts_bits = ts_bytes < 7 ? ts_bytes * 7 : 64; +        int ts_bytes = extractTSField64(m_currPacketData, idx, tsVal); +        int ts_bits; +         +        // if ts_bytes 8 or less, then cont bits on each byte, otherwise full 64 bit value for 9 bytes +        ts_bits = ts_bytes < 9 ? ts_bytes * 7 : 64;          if(!m_curr_packet.pkt_valid.bits.ts_valid && m_first_trace_info)              ts_bits = 64;   // after trace info, missing bits are all 0. @@ -534,6 +557,13 @@ void TrcPktProcEtmV4I::iPktException(const uint8_t lastByte)      case 1: m_excep_size = 3; break;      case 2: if((lastByte & 0x80) == 0x00)                  m_excep_size = 2;  +            // ETE exception reset or trans failed +            if (m_config.MajVersion() >= 0x5) +            { +                excep_type = (m_currPacketData[1] >> 1) & 0x1F; +                if ((excep_type == 0x0) || (excep_type == 0x18)) +                    m_excep_size = 3; +            }              break;      } @@ -553,6 +583,18 @@ void TrcPktProcEtmV4I::iPktException(const uint8_t lastByte)          m_curr_packet.setExceptionInfo(excep_type,addr_interp,m_fault_pending, m_type);          m_process_state = SEND_PKT; +        // ETE exception reset or trans failed +        if (m_config.MajVersion() >= 0x5) +        { +            if ((excep_type == 0x0) || (excep_type == 0x18)) +            { +                m_curr_packet.set64BitAddress(0, 0); +                if (excep_type == 0x18) +                    m_curr_packet.setType(ETE_PKT_I_TRANS_FAIL); +                else +                    m_curr_packet.setType(ETE_PKT_I_PE_RESET); +            } +        }          // allow the standard address packet handlers to process the address packet field for the exception.      }  } @@ -833,7 +875,7 @@ void TrcPktProcEtmV4I::extractAndSetContextInfo(const std::vector<uint8_t> &buff      // on input, buffer index points at the info byte - always present      uint8_t infoByte = m_currPacketData[st_idx]; -    m_curr_packet.setContextInfo(true, (infoByte & 0x3), (infoByte >> 5) & 0x1, (infoByte >> 4) & 0x1);     +    m_curr_packet.setContextInfo(true, (infoByte & 0x3), (infoByte >> 5) & 0x1, (infoByte >> 4) & 0x1, (infoByte >> 3) & 0x1);          // see if there are VMID and CID bytes, and how many.      int nVMID_bytes = ((infoByte & 0x40) == 0x40) ? (m_config.vmidSize()/8) : 0; @@ -937,7 +979,8 @@ void TrcPktProcEtmV4I::iPktShortAddr(const uint8_t lastByte)      {          m_addr_done = false;          m_addrIS = 0; -        if (lastByte == ETM4_PKT_I_ADDR_S_IS1) +        if ((lastByte == ETM4_PKT_I_ADDR_S_IS1) || +            (lastByte == ETE_PKT_I_SRC_ADDR_S_IS1))              m_addrIS = 1;      }      else if(!m_addr_done) @@ -988,14 +1031,18 @@ void TrcPktProcEtmV4I::iPktLongAddr(const uint8_t lastByte)          switch(m_curr_packet.type)          {          case ETM4_PKT_I_ADDR_L_32IS1: +        case ETE_PKT_I_SRC_ADDR_L_32IS1:              m_addrIS = 1;          case ETM4_PKT_I_ADDR_L_32IS0: +        case ETE_PKT_I_SRC_ADDR_L_32IS0:              m_addrBytes = 4;              break;          case ETM4_PKT_I_ADDR_L_64IS1: +        case ETE_PKT_I_SRC_ADDR_L_64IS1:              m_addrIS = 1;          case ETM4_PKT_I_ADDR_L_64IS0: +        case ETE_PKT_I_SRC_ADDR_L_64IS0:              m_addrBytes = 8;              m_bAddr64bit = true;              break; @@ -1203,6 +1250,23 @@ void TrcPktProcEtmV4I::iAtom(const uint8_t lastByte)      m_process_state = SEND_PKT;  } +void TrcPktProcEtmV4I::iPktITE(const uint8_t /* lastByte */) +{ +    uint64_t value; +    int shift = 0; + +    /* packet is always 10 bytes, Header, EL info byte, 8 bytes payload */ +    if (m_currPacketData.size() == 10) { +        value = 0; +        for (int i = 2; i < 10; i++) { +            value |= ((uint64_t)m_currPacketData[i]) << shift; +            shift += 8; +        } +        m_curr_packet.setITE(m_currPacketData[1], value); +        m_process_state = SEND_PKT; +    } +} +  // header byte processing is table driven.  void TrcPktProcEtmV4I::BuildIPacketTable()     { @@ -1247,7 +1311,35 @@ void TrcPktProcEtmV4I::BuildIPacketTable()      // b0000 0111 - exception return       m_i_table[0x07].pkt_type = ETM4_PKT_I_EXCEPT_RTN; -    m_i_table[0x07].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload; +    if (m_config.MajVersion() >= 0x5)  // not valid for ETE +    { +#ifdef ETE_TRACE_ERET_AS_IGNORE +        m_i_table[0x07].pkt_type = ETM4_PKT_I_IGNORE; +        m_i_table[0x07].pptkFn = &EtmV4IPktProcImpl::iPktNoPayload; +#else +        m_i_table[0x07].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg; +#endif +    } +    else +        m_i_table[0x07].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload; + +    // b00001010, b00001011 ETE TRANS packets +    // b00001001 - ETE sw instrumentation packet +    if (m_config.MajVersion() >= 0x5) +    { +        m_i_table[0x0A].pkt_type = ETE_PKT_I_TRANS_ST; +        m_i_table[0x0A].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload; + +        m_i_table[0x0B].pkt_type = ETE_PKT_I_TRANS_COMMIT; +        m_i_table[0x0B].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload; + +        // FEAT_ITE - sw instrumentation packet +        if (m_config.MinVersion() >= 0x3) +        { +            m_i_table[0x09].pkt_type = ETE_PKT_I_ITE; +            m_i_table[0x09].pptkFn = &TrcPktProcEtmV4I::iPktITE; +        } +    }      // b0000 110x - cycle count f2      // b0000 111x - cycle count f1 @@ -1443,6 +1535,12 @@ void TrcPktProcEtmV4I::BuildIPacketTable()          m_i_table[0x85+i].pptkFn   = &TrcPktProcEtmV4I::iPktAddrCtxt;      } +    // 0b1000 1000 - ETE 1.1 TS Marker. also ETMv4.6 +    if(m_config.FullVersion() >= 0x46) +    { +        m_i_table[0x88].pkt_type = ETE_PKT_I_TS_MARKER; +        m_i_table[0x88].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload; +    }      // 0b1001 0000 to b1001 0010 - exact match addr      for(int i = 0; i < 3; i++)      { @@ -1492,6 +1590,30 @@ void TrcPktProcEtmV4I::BuildIPacketTable()          }      } +    // b10110000 - b10111001 - ETE src address packets +    if (m_config.FullVersion() >= 0x50) +    { +        for (int i = 0; i < 3; i++) +        { +            m_i_table[0xB0 + i].pkt_type = ETE_PKT_I_SRC_ADDR_MATCH; +            m_i_table[0xB0 + i].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload; +        } + +        m_i_table[0xB4].pkt_type = ETE_PKT_I_SRC_ADDR_S_IS0; +        m_i_table[0xB4].pptkFn = &TrcPktProcEtmV4I::iPktShortAddr; +        m_i_table[0xB5].pkt_type = ETE_PKT_I_SRC_ADDR_S_IS1; +        m_i_table[0xB5].pptkFn = &TrcPktProcEtmV4I::iPktShortAddr; + +        m_i_table[0xB6].pkt_type = ETE_PKT_I_SRC_ADDR_L_32IS0; +        m_i_table[0xB6].pptkFn = &TrcPktProcEtmV4I::iPktLongAddr; +        m_i_table[0xB7].pkt_type = ETE_PKT_I_SRC_ADDR_L_32IS1; +        m_i_table[0xB7].pptkFn = &TrcPktProcEtmV4I::iPktLongAddr; +        m_i_table[0xB8].pkt_type = ETE_PKT_I_SRC_ADDR_L_64IS0; +        m_i_table[0xB8].pptkFn = &TrcPktProcEtmV4I::iPktLongAddr; +        m_i_table[0xB9].pkt_type = ETE_PKT_I_SRC_ADDR_L_64IS1; +        m_i_table[0xB9].pptkFn = &TrcPktProcEtmV4I::iPktLongAddr; +    } +      // Atom Packets - all no payload but have specific pattern generation fn      for(int i = 0xC0; i <= 0xD4; i++)   // atom f6      { @@ -1559,20 +1681,33 @@ void TrcPktProcEtmV4I::BuildIPacketTable()      return idx;  } -unsigned TrcPktProcEtmV4I::extractContField64(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint64_t &value, const unsigned byte_limit /*= 9*/) +unsigned TrcPktProcEtmV4I::extractTSField64(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint64_t &value)  { +    const unsigned max_byte_idx = 8;    /* the 9th byte, index 8, will use full 8 bits for value */      unsigned idx = 0;      bool lastByte = false;      uint8_t byteVal; +    uint8_t byteValMask = 0x7f; +     +    /* init value */      value = 0; -    while(!lastByte && (idx < byte_limit))   // max 9 bytes for 64 bit value; +    while(!lastByte)   // max 9 bytes for 64 bit value;      {          if(buffer.size() > (st_idx + idx))          {              // each byte has seven bits + cont bit              byteVal = buffer[(st_idx + idx)]; -            lastByte = (byteVal & 0x80) != 0x80; -            value |= ((uint64_t)(byteVal & 0x7F)) << (idx * 7); + +            /* detect the final byte - which uses full 8 bits as value */ +            if (idx == max_byte_idx) +            { +                byteValMask = 0xFF;  /* last byte of 9, no cont bit */ +                lastByte = true; +            } +            else  +                lastByte = (byteVal & 0x80) != 0x80; + +            value |= ((uint64_t)(byteVal & byteValMask)) << (idx * 7);              idx++;          }          else @@ -1580,6 +1715,7 @@ unsigned TrcPktProcEtmV4I::extractContField64(const std::vector<uint8_t> &buffer              throwBadSequenceError("Invalid 64 bit continuation fields in packet");          }      } +    // index is the count of bytes used here.      return idx;  } diff --git a/decoder/source/i_dec/trc_i_decode.cpp b/decoder/source/i_dec/trc_i_decode.cpp index 614fc1d8b45c..0e0589512002 100644 --- a/decoder/source/i_dec/trc_i_decode.cpp +++ b/decoder/source/i_dec/trc_i_decode.cpp @@ -42,7 +42,7 @@ ocsd_err_t TrcIDecode::DecodeInstruction(ocsd_instr_info *instr_info)      struct decode_info info;      info.instr_sub_type = OCSD_S_INSTR_NONE; -    info.arch_version = (uint16_t)(instr_info->pe_type.arch); +    info.arch_version = instr_info->pe_type.arch;      switch(instr_info->isa)      { @@ -136,14 +136,12 @@ ocsd_err_t TrcIDecode::DecodeA64(ocsd_instr_info *instr_info, struct decode_info      if(inst_A64_is_indirect_branch_link(instr_info->opcode, &instr_info->is_link, info))      {          instr_info->type = OCSD_INSTR_BR_INDIRECT; -//        instr_info->is_link = inst_A64_is_branch_and_link(instr_info->opcode);      }      else if(inst_A64_is_direct_branch_link(instr_info->opcode, &instr_info->is_link, info))      {          inst_A64_branch_destination(instr_info->instr_addr,instr_info->opcode,&branchAddr);          instr_info->type = OCSD_INSTR_BR;          instr_info->branch_addr = (ocsd_vaddr_t)branchAddr; -//        instr_info->is_link = inst_A64_is_branch_and_link(instr_info->opcode);      }      else if((barrier = inst_A64_barrier(instr_info->opcode)) != ARM_BARRIER_NONE)      { @@ -160,12 +158,15 @@ ocsd_err_t TrcIDecode::DecodeA64(ocsd_instr_info *instr_info, struct decode_info              break;          }      } -    else if (instr_info->wfi_wfe_branch) +    else if (instr_info->wfi_wfe_branch &&  +             inst_A64_wfiwfe(instr_info->opcode, info))      { -        if (inst_A64_wfiwfe(instr_info->opcode)) -        { -            instr_info->type = OCSD_INSTR_WFI_WFE; -        } +        instr_info->type = OCSD_INSTR_WFI_WFE; +    } +    else if (OCSD_IS_ARCH_MINVER(info->arch_version, ARCH_AA64)) +    { +        if (inst_A64_Tstart(instr_info->opcode)) +            instr_info->type = OCSD_INSTR_TSTART;      }      instr_info->is_conditional = inst_A64_is_conditional(instr_info->opcode); diff --git a/decoder/source/i_dec/trc_idec_arminst.cpp b/decoder/source/i_dec/trc_idec_arminst.cpp index 3652e84921f3..76951fd38183 100644 --- a/decoder/source/i_dec/trc_idec_arminst.cpp +++ b/decoder/source/i_dec/trc_idec_arminst.cpp @@ -244,8 +244,9 @@ int inst_A64_is_direct_branch_link(uint32_t inst, uint8_t *is_link, struct decod      int is_direct_branch = 1;      if ((inst & 0x7c000000) == 0x34000000) {          /* CB, TB */ -    } else if ((inst & 0xff000010) == 0x54000000) { +    } else if ((inst & 0xff000000) == 0x54000000) {          /* B<cond> */ +        /* BC<cond> 8.8 / 9.3 arch - bit 4 = 1'b1 */      } else if ((inst & 0x7c000000) == 0x14000000) {          /* B, BL imm */          if (inst & 0x80000000) { @@ -258,11 +259,26 @@ int inst_A64_is_direct_branch_link(uint32_t inst, uint8_t *is_link, struct decod      return is_direct_branch;  } -int inst_A64_wfiwfe(uint32_t inst) +int inst_A64_wfiwfe(uint32_t inst, struct decode_info *info)  {      /* WFI, WFE may be traced as branches in etm 4.3++ */      if ((inst & 0xffffffdf) == 0xd503205f)          return 1; + +    /* new feature introduced post v8.3 */ +    if (OCSD_IS_ARCH_MINVER(info->arch_version, ARCH_AA64)) +    { +        /* WFIT / WFET for later archs */ +        if ((inst & 0xffffffc0) == 0xd5031000) +            return 1; +    } +    return 0; +} + +int inst_A64_Tstart(uint32_t inst) +{ +    if ((inst & 0xffffffe0) == 0xd5233060) +        return 1;      return 0;  } @@ -288,7 +304,7 @@ int inst_A64_is_indirect_branch_link(uint32_t inst, uint8_t *is_link, struct dec      } else if ((inst & 0xffffffff) == 0xd69f03e0) {          /* ERET */          info->instr_sub_type = OCSD_S_INSTR_V8_ERET; -    } else if (info->arch_version >= 0x0803) { +    } else if (OCSD_IS_ARCH_MINVER(info->arch_version, ARCH_V8r3)) {          /* new pointer auth instr for v8.3 arch */             if ((inst & 0xffdff800) == 0xd71f0800) {              /* BRAA, BRAB, BLRAA, BLRBB */ @@ -399,8 +415,9 @@ int inst_A64_branch_destination(uint64_t addr, uint32_t inst, uint64_t *pnpc)  {      uint64_t npc;      int is_direct_branch = 1; -    if ((inst & 0xff000010) == 0x54000000) { +    if ((inst & 0xff000000) == 0x54000000) {          /* B<cond> */ +        /* BC<cond> */          npc = addr + ((int32_t)((inst & 0x00ffffe0) << 8) >> 11);      } else if ((inst & 0x7c000000) == 0x14000000) {          /* B, BL imm */ @@ -484,7 +501,7 @@ int inst_A64_is_branch_and_link(uint32_t inst, struct decode_info *info)      } else if ((inst & 0xfc000000) == 0x94000000) {          /* BL */          info->instr_sub_type = OCSD_S_INSTR_BR_LINK; -    }  else if (info->arch_version >= 0x0803) { +    }  else if (OCSD_IS_ARCH_MINVER(info->arch_version, ARCH_V8r3)) {          /* new pointer auth instr for v8.3 arch */          if ((inst & 0xfffff800) == 0xd73f0800) {              /* BLRAA, BLRBB */ @@ -553,8 +570,9 @@ int inst_A64_is_conditional(uint32_t inst)      if ((inst & 0x7c000000) == 0x34000000) {          /* CB, TB */          return 1; -    } else if ((inst & 0xff000010) == 0x54000000) { +    } else if ((inst & 0xff000000) == 0x54000000) {          /* B.cond */ +        /* BC.cond */          return 1;      }      return 0; diff --git a/decoder/source/mem_acc/trc_mem_acc_mapper.cpp b/decoder/source/mem_acc/trc_mem_acc_mapper.cpp index 53edfe1a1616..dc07a1ed5a25 100644 --- a/decoder/source/mem_acc/trc_mem_acc_mapper.cpp +++ b/decoder/source/mem_acc/trc_mem_acc_mapper.cpp @@ -119,6 +119,14 @@ ocsd_err_t TrcMemAccMapper::ReadTargetMemory(const ocsd_vaddr_t address, const u      return err;  } +void TrcMemAccMapper::InvalidateMemAccCache(const uint8_t /* cs_trace_id */) +{ +    // default mapper does not use cs_trace_id for cache invalidation. +    if (m_cache.enabled()) +        m_cache.invalidateAll(); +    m_acc_curr = 0; +} +  void TrcMemAccMapper::RemoveAllAccessors()  {      TrcMemAccessorBase *pAcc = 0; diff --git a/decoder/source/ocsd_dcd_tree.cpp b/decoder/source/ocsd_dcd_tree.cpp index be15e36e9cb3..8e29269d1690 100644 --- a/decoder/source/ocsd_dcd_tree.cpp +++ b/decoder/source/ocsd_dcd_tree.cpp @@ -101,6 +101,13 @@ DecodeTree::DecodeTree() :  {      for(int i = 0; i < 0x80; i++)          m_decode_elements[i] = 0; + +     // reset the global demux stats. +    m_demux_stats.frame_bytes = 0; +    m_demux_stats.no_id_bytes = 0; +    m_demux_stats.valid_id_bytes = 0;   +    m_demux_stats.unknown_id_bytes = 0; +    m_demux_stats.reserved_id_bytes = 0;       }  DecodeTree::~DecodeTree() @@ -486,6 +493,62 @@ ocsd_err_t DecodeTree::removeDecoder(const uint8_t CSID)      return err;  } +ocsd_err_t DecodeTree::getDecoderStats(const uint8_t CSID, ocsd_decode_stats_t **p_stats_block) +{ +    ocsd_err_t err = OCSD_OK; +    TrcPktProcI *pPktProc = getPktProcI(CSID); +    if (!pPktProc) +        return OCSD_ERR_INVALID_PARAM_VAL; +    err = pPktProc->getStatsBlock(p_stats_block); +    if (err == OCSD_OK) { +        // copy in the global demux stats. +        (*p_stats_block)->demux.frame_bytes = m_demux_stats.frame_bytes; +        (*p_stats_block)->demux.no_id_bytes = m_demux_stats.no_id_bytes; +        (*p_stats_block)->demux.valid_id_bytes = m_demux_stats.valid_id_bytes; +        (*p_stats_block)->demux.unknown_id_bytes = m_demux_stats.unknown_id_bytes; +        (*p_stats_block)->demux.reserved_id_bytes = m_demux_stats.reserved_id_bytes; +    } +    return err; +} + +ocsd_err_t DecodeTree::resetDecoderStats(const uint8_t CSID) +{ +    TrcPktProcI *pPktProc = getPktProcI(CSID); +    if (!pPktProc) +        return OCSD_ERR_INVALID_PARAM_VAL; +    pPktProc->resetStats(); + +    // reset the global demux stats. +    m_demux_stats.frame_bytes = 0; +    m_demux_stats.no_id_bytes = 0; +    m_demux_stats.valid_id_bytes = 0;   +    m_demux_stats.unknown_id_bytes = 0; +    m_demux_stats.reserved_id_bytes = 0; +    return OCSD_OK; +} + +TrcPktProcI *DecodeTree::getPktProcI(const uint8_t CSID) +{ +    TrcPktProcI *pPktProc = 0; +    TraceComponent *pComp, *pAssoc; +    DecodeTreeElement *pElem = getDecoderElement(CSID); +     +    if (pElem)  +    { +        pComp = pElem->getDecoderHandle(); +        if (pComp) +        { +            /* if this is a full decoder then the associated component is the packet processor */ +            pAssoc = pComp->getAssocComponent(); +            if (pAssoc) +                pPktProc = dynamic_cast<TrcPktProcI *>(pAssoc); +            else +                pPktProc = dynamic_cast<TrcPktProcI *>(pComp); +        } +    } +    return pPktProc; +} +  DecodeTreeElement * DecodeTree::getDecoderElement(const uint8_t CSID) const  {      DecodeTreeElement *ret_elem = 0; @@ -511,7 +574,7 @@ DecodeTreeElement *DecodeTree::getNextElement(uint8_t &elemID)      if(m_decode_elem_iter < 0x80)      {          // find a none zero entry or end of range -        while((m_decode_elements[m_decode_elem_iter] == 0) && (m_decode_elem_iter < 0x80)) +        while((m_decode_elem_iter < 0x80) && (m_decode_elements[m_decode_elem_iter] == 0))              m_decode_elem_iter++;          // return entry unless end of range @@ -527,7 +590,7 @@ DecodeTreeElement *DecodeTree::getNextElement(uint8_t &elemID)  bool DecodeTree::initialise(const ocsd_dcd_tree_src_t type, uint32_t formatterCfgFlags)  { -    bool initOK = true; +    ocsd_err_t err;       m_dcd_tree_type = type;      if(type ==  OCSD_TRC_SRC_FRAME_FORMATTED)      { @@ -535,14 +598,19 @@ bool DecodeTree::initialise(const ocsd_dcd_tree_src_t type, uint32_t formatterCf          m_frame_deformatter_root = new (std::nothrow) TraceFormatterFrameDecoder();          if(m_frame_deformatter_root)          { -            m_frame_deformatter_root->Configure(formatterCfgFlags); +            if (m_frame_deformatter_root->Init() != OCSD_OK) +                return false;              m_frame_deformatter_root->getErrLogAttachPt()->attach(DecodeTree::s_i_error_logger); +            err = m_frame_deformatter_root->Configure(formatterCfgFlags); +            if (err != OCSD_OK) +                return false;              m_i_decoder_root = dynamic_cast<ITrcDataIn*>(m_frame_deformatter_root); +            m_frame_deformatter_root->SetDemuxStatsBlock(&m_demux_stats);          }          else  -            initOK = false; +            return false;      } -    return initOK; +    return true;  }  void DecodeTree::setSingleRoot(TrcPktProcI *pComp) @@ -621,6 +689,7 @@ ocsd_err_t DecodeTree::addPacketPrinter(uint8_t CSID, bool bMonitor, ItemPrinter              switch (protocol)              {              case  OCSD_PROTOCOL_ETMV4I: +            case  OCSD_PROTOCOL_ETE:              {                  PacketPrinter<EtmV4ITrcPacket> *pTPrinter = dynamic_cast<PacketPrinter<EtmV4ITrcPacket> *>(pPrinter);                  if (bMonitor) diff --git a/decoder/source/ocsd_error.cpp b/decoder/source/ocsd_error.cpp index 74e9e4977f60..ee01064a3476 100644 --- a/decoder/source/ocsd_error.cpp +++ b/decoder/source/ocsd_error.cpp @@ -229,4 +229,25 @@ void ocsdError::appendErrorDetails(std::string &errStr, const ocsdError &error)      errStr = oss.str();  } + +const char* ocsdDataRespStr::getStr() +{ +    static const char* szRespStr[] = { +    "OCSD_RESP_CONT: Continue processing.", +    "OCSD_RESP_WARN_CONT: Continue processing -> a component logged a warning.", +    "OCSD_RESP_ERR_CONT: Continue processing -> a component logged an error.", +    "OCSD_RESP_WAIT: Pause processing", +    "OCSD_RESP_WARN_WAIT: Pause processing -> a component logged a warning.", +    "OCSD_RESP_ERR_WAIT: Pause processing -> a component logged an error.", +    "OCSD_RESP_FATAL_NOT_INIT: Processing Fatal Error :  component unintialised.", +    "OCSD_RESP_FATAL_INVALID_OP: Processing Fatal Error :  invalid data path operation.", +    "OCSD_RESP_FATAL_INVALID_PARAM: Processing Fatal Error :  invalid parameter in datapath call.", +    "OCSD_RESP_FATAL_INVALID_DATA: Processing Fatal Error :  invalid trace data.", +    "OCSD_RESP_FATAL_SYS_ERR: Processing Fatal Error :  internal system error." +    }; +    if ((m_type < OCSD_RESP_CONT) || (m_type > OCSD_RESP_FATAL_SYS_ERR)) +        return "Unknown OCSD_RESP type."; +    return szRespStr[m_type]; +} +  /* End of File ocsd_error.cpp */ diff --git a/decoder/source/ocsd_gen_elem_stack.cpp b/decoder/source/ocsd_gen_elem_stack.cpp index bb758427a9b8..66fe75d9899a 100644 --- a/decoder/source/ocsd_gen_elem_stack.cpp +++ b/decoder/source/ocsd_gen_elem_stack.cpp @@ -42,6 +42,7 @@ OcsdGenElemStack::OcsdGenElemStack() :      m_curr_elem_idx(0),      m_send_elem_idx(0),      m_CSID(0), +    m_sendIf(NULL),      m_is_init(false)  { diff --git a/decoder/source/ocsd_lib_dcd_register.cpp b/decoder/source/ocsd_lib_dcd_register.cpp index adb042dcadff..0233c89eaa06 100644 --- a/decoder/source/ocsd_lib_dcd_register.cpp +++ b/decoder/source/ocsd_lib_dcd_register.cpp @@ -39,13 +39,15 @@  #include "opencsd/etmv3/trc_dcd_mngr_etmv3.h"  #include "opencsd/ptm/trc_dcd_mngr_ptm.h"  #include "opencsd/stm/trc_dcd_mngr_stm.h" +#include "opencsd/ete/trc_dcd_mngr_ete.h"  // create array of built-in decoders to register with library   static built_in_decoder_info_t sBuiltInArray[] = {      CREATE_BUILTIN_ENTRY(DecoderMngrEtmV4I,OCSD_BUILTIN_DCD_ETMV4I),      CREATE_BUILTIN_ENTRY(DecoderMngrEtmV3, OCSD_BUILTIN_DCD_ETMV3),      CREATE_BUILTIN_ENTRY(DecoderMngrPtm, OCSD_BUILTIN_DCD_PTM), -    CREATE_BUILTIN_ENTRY(DecoderMngrStm, OCSD_BUILTIN_DCD_STM) +    CREATE_BUILTIN_ENTRY(DecoderMngrStm, OCSD_BUILTIN_DCD_STM), +    CREATE_BUILTIN_ENTRY(DecoderMngrETE, OCSD_BUILTIN_DCD_ETE)      //{ 0, 0, 0}  }; @@ -90,7 +92,6 @@ OcsdLibDcdRegister::~OcsdLibDcdRegister()      m_pLastTypedDecoderMngr = 0;  } -  const ocsd_err_t OcsdLibDcdRegister::registerDecoderTypeByName(const std::string &name, IDecoderMngr *p_decoder_fact)  {      if(isRegisteredDecoder(name)) diff --git a/decoder/source/pkt_printers/trc_print_fact.cpp b/decoder/source/pkt_printers/trc_print_fact.cpp index 52dcb6b3e1ac..6b5df1f472e0 100644 --- a/decoder/source/pkt_printers/trc_print_fact.cpp +++ b/decoder/source/pkt_printers/trc_print_fact.cpp @@ -55,8 +55,9 @@ ItemPrinter *PktPrinterFact::createProtocolPrinter(std::vector<ItemPrinter *> &p  {      ItemPrinter *pPrinter = 0;      switch (protocol) -    { +    {          case OCSD_PROTOCOL_ETMV4I: +    case OCSD_PROTOCOL_ETE:          pPrinter = new (std::nothrow) PacketPrinter<EtmV4ITrcPacket>(CSID);          break;      case OCSD_PROTOCOL_ETMV3: diff --git a/decoder/source/ptm/trc_pkt_proc_ptm.cpp b/decoder/source/ptm/trc_pkt_proc_ptm.cpp index 7c90b62e6413..668a14b73df0 100644 --- a/decoder/source/ptm/trc_pkt_proc_ptm.cpp +++ b/decoder/source/ptm/trc_pkt_proc_ptm.cpp @@ -224,6 +224,7 @@ void TrcPktProcPtm::InitProcessorState()      m_waitASyncSOPkt = false;      m_bAsyncRawOp = false;      m_bOPNotSyncPkt = false; +    m_excepAltISA = 0;      m_curr_packet.ResetState();      InitPacketState(); @@ -559,7 +560,7 @@ void TrcPktProcPtm::pktWPointUpdate()          m_gotExcepBytes = false;    // mark as not got all required exception bytes thus far          m_numExcepBytes = 0;        // 0 read in -         m_addrPktIsa = ocsd_isa_unknown; // not set by this packet as yet         +        m_addrPktIsa = ocsd_isa_unknown; // not set by this packet as yet              }      // collect all the bytes needed @@ -567,10 +568,12 @@ void TrcPktProcPtm::pktWPointUpdate()      {          if(readByte(currByte))          { +                          byteIdx = m_currPacketData.size() - 1;              if(!m_gotAddrBytes)              { -                if(byteIdx < 4) +                // byteIdx for address byte will run from 1 to 5 - first 4 my have continuation or not. +                if(byteIdx <= 4)                  {                      // address bytes  1 - 4;                      // ISA stays the same diff --git a/decoder/source/trc_core_arch_map.cpp b/decoder/source/trc_core_arch_map.cpp index a26f79db996e..f25ab1e5ddfa 100644 --- a/decoder/source/trc_core_arch_map.cpp +++ b/decoder/source/trc_core_arch_map.cpp @@ -72,17 +72,6 @@ static ap_map_elem_t ap_map_array[] =      { "Cortex-M4", { ARCH_V7, profile_CortexM } }  };    -static ap_map_elem_t arch_map_array[] =  -{ -    { "ARMv7-A", { ARCH_V7, profile_CortexA } }, -    { "ARMv7-R", { ARCH_V7, profile_CortexR } }, -    { "ARMv7-M", { ARCH_V7, profile_CortexM } }, -    { "ARMv8-A", { ARCH_V8, profile_CortexA } }, -    { "ARMv8.3-A", { ARCH_V8r3, profile_CortexA } }, -    { "ARMv8-R", { ARCH_V8, profile_CortexR } }, -    { "ARMv8-M", { ARCH_V8, profile_CortexM } }, -}; -  CoreArchProfileMap::CoreArchProfileMap()  {      unsigned i; @@ -90,10 +79,99 @@ CoreArchProfileMap::CoreArchProfileMap()      {          core_profiles[ap_map_array[i].name] = ap_map_array[i].ap;      } -    for (i = 0; i < sizeof(arch_map_array) / sizeof(_ap_map_elements); i++) +} + +ocsd_arch_profile_t CoreArchProfileMap::getArchProfile(const std::string &coreName) +{ +    ocsd_arch_profile_t ap = { ARCH_UNKNOWN, profile_Unknown }; +    bool bFound = false; + +    std::map<std::string, ocsd_arch_profile_t>::const_iterator it; + +    /* match against the core name map. */ +    it = core_profiles.find(coreName); +    if (it != core_profiles.end())      { -        arch_profiles[arch_map_array[i].name] = arch_map_array[i].ap; +        ap = it->second; +        bFound = true;      } + +    /* try a pattern match on core name - pick up ARMvM[.m]-P and ARM-{aa|AA}64[-P] */ +    if (!bFound) +        ap = getPatternMatchCoreName(coreName); + +    return ap;  } +ocsd_arch_profile_t CoreArchProfileMap::getPatternMatchCoreName(const std::string &coreName) +{ +    ocsd_arch_profile_t ap = { ARCH_UNKNOWN, profile_Unknown }; +    size_t pos; +    /* look for ARMvM[.m]-P */ +    pos = coreName.find("ARMv"); +    if (pos == 0) +    { +        int majver = coreName[4] - '0'; +        int minver = 0; +        int dotoffset = 0; + +        pos = coreName.find_first_of("."); +        if (pos == 5) { +            minver = coreName[6] - '0'; +            dotoffset = 2; +        } +        else if (pos != std::string::npos) +            return ap; + +        if (majver == 7) +            ap.arch = ARCH_V7; +        else if (majver >= 8) { +            ap.arch = ARCH_AA64; /* default to 8.3+*/ +            if (majver == 8) { +                if (minver < 3) +                    ap.arch = ARCH_V8; +                else if (minver == 3) +                    ap.arch = ARCH_V8r3; +            } +        } +        else +            return ap; /* no valid version  - return unknown */ + +        if (coreName.find_first_of("-", 4) == (size_t)(5 + dotoffset)) { +            int profile_idx = 6 + dotoffset; +            if (coreName[profile_idx] == 'A') +                ap.profile = profile_CortexA; +            else if (coreName[profile_idx] == 'R') +                ap.profile = profile_CortexR; +            else if (coreName[profile_idx] == 'M') +                ap.profile = profile_CortexM; +            else +                ap.arch = ARCH_UNKNOWN; /*reset arch, return unknown*/ +        } +        else +            ap.arch = ARCH_UNKNOWN; /*reset arch, return unknown*/ +        return ap; +    } + +    /* look for ARM-{AA|aa}64[-P] */ +    pos = coreName.find("ARM-"); +    if (pos == 0) +    { +        pos = coreName.find("aa64"); +        if (pos != 4) +            pos = coreName.find("AA64"); +        if (pos == 4) +        { +            ap.arch = ARCH_AA64; +            ap.profile = profile_CortexA; +            if (coreName.find_first_of("-", 7) == 8) { +                if (coreName[9] == 'R') +                    ap.profile = profile_CortexR; +                else if (coreName[9] == 'M') +                    ap.profile = profile_CortexM; +            } +        } +    } +    return ap; +}  /* End of File trc_core_arch_map.cpp */ diff --git a/decoder/source/trc_frame_deformatter.cpp b/decoder/source/trc_frame_deformatter.cpp index 4d46854a655b..3b2aead875ca 100644 --- a/decoder/source/trc_frame_deformatter.cpp +++ b/decoder/source/trc_frame_deformatter.cpp @@ -54,7 +54,8 @@ TraceFmtDcdImpl::TraceFmtDcdImpl() : TraceComponent(DEFORMATTER_NAME),      m_use_force_sync(false),      m_alignment(16), // assume frame aligned data as default.      m_b_output_packed_raw(false), -    m_b_output_unpacked_raw(false) +    m_b_output_unpacked_raw(false), +    m_pStatsBlock(0)  {      resetStateParams(); @@ -244,7 +245,12 @@ ocsd_datapath_resp_t TraceFmtDcdImpl::processTraceData(              if(m_trc_curr_idx != index) // none continuous trace data - throw an error.                  throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_DFMTR_NOTCONTTRACE,index);          } -         + +        // record the incoming block for extraction routines to use. +        m_in_block_base = pDataBlock; +        m_in_block_size = dataBlockSize; +        m_in_block_processed = 0; +          if(dataBlockSize % m_alignment) // must be correctly aligned data           {              ocsdError err(OCSD_ERR_SEV_ERROR, OCSD_ERR_INVALID_PARAM_VAL); @@ -254,11 +260,6 @@ ocsd_datapath_resp_t TraceFmtDcdImpl::processTraceData(              throw ocsdError(&err);          } -        // record the incoming block for extraction routines to use. -        m_in_block_base = pDataBlock; -        m_in_block_size = dataBlockSize; -        m_in_block_processed = 0; -          // processing loop...          if(checkForSync())          { @@ -324,12 +325,18 @@ ocsd_err_t  TraceFmtDcdImpl::DecodeConfigure(uint32_t flags)      }      else      { +        // alightment is the multiple of bytes the buffer size must be.          m_cfgFlags = flags; + +        // using memory aligned buffers, the formatter always outputs 16 byte frames so enforce +        // this on the input          m_alignment = 16; -        if(flags & OCSD_DFRMTR_HAS_FSYNCS) -            m_alignment = 4; -        else if(flags & OCSD_DFRMTR_HAS_HSYNCS) +        // if we have HSYNCS then always align to 2 byte buffers +        if(flags & OCSD_DFRMTR_HAS_HSYNCS)              m_alignment = 2; +        // otherwise FSYNCS only can have 4 byte aligned buffers. +        else if(flags & OCSD_DFRMTR_HAS_FSYNCS) +            m_alignment = 4;      }      return err;  } @@ -344,6 +351,7 @@ void TraceFmtDcdImpl::resetStateParams()      // current frame processing      m_ex_frm_n_bytes = 0; +    m_b_fsync_start_eob = false;      m_trc_curr_idx_sof = OCSD_BAD_TRC_INDEX;  } @@ -415,20 +423,23 @@ void TraceFmtDcdImpl::outputUnsyncedBytes(uint32_t /*num_bytes*/)      //**TBD:  } -int TraceFmtDcdImpl::checkForResetFSyncPatterns() +ocsd_err_t TraceFmtDcdImpl::checkForResetFSyncPatterns(uint32_t &f_sync_bytes)  {  	const uint32_t FSYNC_PATTERN = 0x7FFFFFFF;    // LE host pattern for FSYNC	   	bool check_for_fsync = true;  	int num_fsyncs = 0; -	const uint8_t *dataPtr = m_in_block_base + m_in_block_processed; +    uint32_t bytes_processed = m_in_block_processed; +	const uint8_t *dataPtr = m_in_block_base + bytes_processed; +    ocsd_err_t err = OCSD_OK; -	while (check_for_fsync && (m_in_block_processed < m_in_block_size)) +	while (check_for_fsync && (bytes_processed < m_in_block_size))  	{  		// look for consecutive fsyncs as padding or for reset downstream - both cases will reset downstream....  		if (*((uint32_t *)(dataPtr)) == FSYNC_PATTERN)  		{  			dataPtr += sizeof(uint32_t); -			num_fsyncs++;		 +            num_fsyncs++; +            bytes_processed += sizeof(uint32_t);  		}  		else  			check_for_fsync = false; @@ -436,7 +447,6 @@ int TraceFmtDcdImpl::checkForResetFSyncPatterns()  	if (num_fsyncs)  	{ -        printf("Frame deformatter: Found %d FSYNCS\n",num_fsyncs);  		if ((num_fsyncs % 4) == 0)          {              // reset the upstream decoders             @@ -449,32 +459,40 @@ int TraceFmtDcdImpl::checkForResetFSyncPatterns()          }  		else  		{ -			// TBD: throw processing error, none frame size block of fsyncs +            err = OCSD_ERR_DFMTR_BAD_FHSYNC;  		}  	} -    return num_fsyncs * 4; +    f_sync_bytes += num_fsyncs * 4; +    return err;  } - +/* Extract a single frame from the input buffer. */  bool TraceFmtDcdImpl::extractFrame()  {  	const uint32_t FSYNC_PATTERN = 0x7FFFFFFF;    // LE host pattern for FSYNC	   	const uint16_t HSYNC_PATTERN = 0x7FFF;        // LE host pattern for HSYNC +    const uint16_t FSYNC_START = 0xFFFF;          // LE host pattern for start 2 bytes of fsync -	 -	bool cont_process = true;   // continue processing after extraction. +    ocsd_err_t err;      uint32_t f_sync_bytes = 0; // skipped f sync bytes      uint32_t h_sync_bytes = 0; // skipped h sync bytes      uint32_t ex_bytes = 0;  // extracted this pass (may be filling out part frame) +    uint32_t buf_left = m_in_block_size - m_in_block_processed; // bytes remaining in buffer this pass. -    // memory aligned sources are always multiples of frames, aligned to start. +    // last call was end of input block - but carried on to process full frame. +    // exit early here. +    if (!buf_left) +        return false; + +    // memory aligned input data is forced to be always multiples of 16 byte frames, aligned to start.      if( m_cfgFlags & OCSD_DFRMTR_FRAME_MEM_ALIGN)      {  		// some linux drivers (e.g. for perf) will insert FSYNCS to pad or differentiate -        // between blocks of aligned data, always in frame aligned complete 16 byte frames.        +        // between blocks of aligned data, always in frame aligned complete 16 byte frames. +        // we need to skip past these frames, resetting as we go.          if (m_cfgFlags & OCSD_DFRMTR_RESET_ON_4X_FSYNC)          { -            f_sync_bytes = checkForResetFSyncPatterns(); +             err = checkForResetFSyncPatterns(f_sync_bytes);              /* in this case the FSYNC pattern is output on both packed and unpacked cases */              if (f_sync_bytes && (m_b_output_packed_raw || m_b_output_unpacked_raw)) @@ -486,77 +504,96 @@ bool TraceFmtDcdImpl::extractFrame()                      m_in_block_base + m_in_block_processed,                      0);              } + +            // throw processing error, none frame size block of fsyncs +            if (err) +                throw ocsdError(OCSD_ERR_SEV_ERROR, err, m_trc_curr_idx, "Incorrect FSYNC frame reset pattern"); + +            buf_left -= f_sync_bytes;          } -        if((m_in_block_processed+f_sync_bytes) == m_in_block_size) +        if (buf_left)          { -            m_ex_frm_n_bytes = 0; -            cont_process = false;   // end of input data. -        } -		else -		{ -			// always a complete frame. -			m_ex_frm_n_bytes = OCSD_DFRMTR_FRAME_SIZE; -			memcpy(m_ex_frm_data, m_in_block_base + m_in_block_processed + f_sync_bytes, m_ex_frm_n_bytes); -			m_trc_curr_idx_sof = m_trc_curr_idx + f_sync_bytes; -			ex_bytes = OCSD_DFRMTR_FRAME_SIZE; +            // always a complete frame - the input data has to be 16 byte multiple alignment. +            m_ex_frm_n_bytes = OCSD_DFRMTR_FRAME_SIZE; +            memcpy(m_ex_frm_data, m_in_block_base + m_in_block_processed + f_sync_bytes, m_ex_frm_n_bytes); +            m_trc_curr_idx_sof = m_trc_curr_idx + f_sync_bytes; +            ex_bytes = OCSD_DFRMTR_FRAME_SIZE;          }      }      else      {          // extract data accounting for frame syncs and hsyncs if present.          // we know we are aligned at this point - could be FSYNC or HSYNCs here. +        // HSYNC present, library forces input to be aligned 2 byte multiples +        // FSYNC - w/o HSYNCs, forces input to be aligned 4 byte multiples.          // check what we a looking for -        bool hasFSyncs =  ((m_cfgFlags & OCSD_DFRMTR_HAS_FSYNCS) == OCSD_DFRMTR_HAS_FSYNCS); -        bool hasHSyncs =  ((m_cfgFlags & OCSD_DFRMTR_HAS_HSYNCS) == OCSD_DFRMTR_HAS_HSYNCS); +        bool hasFSyncs = ((m_cfgFlags & OCSD_DFRMTR_HAS_FSYNCS) == OCSD_DFRMTR_HAS_FSYNCS); +        bool hasHSyncs = ((m_cfgFlags & OCSD_DFRMTR_HAS_HSYNCS) == OCSD_DFRMTR_HAS_HSYNCS); + +        const uint8_t* dataPtr = m_in_block_base + m_in_block_processed; +        uint16_t data_pair_val; -        const uint8_t *dataPtr = m_in_block_base+m_in_block_processed; -        const uint8_t *eodPtr = m_in_block_base+m_in_block_size; -         -        cont_process = (bool)(dataPtr < eodPtr); -                  // can have FSYNCS at start of frame (in middle is an error). -        if(hasFSyncs && cont_process && (m_ex_frm_n_bytes == 0)) +        if (hasFSyncs && (m_ex_frm_n_bytes == 0))          { -            while((*((uint32_t *)(dataPtr)) == FSYNC_PATTERN) && cont_process) +            // was there an fsync start at the end of the last buffer? +            if (m_b_fsync_start_eob) { +                // last 2 of FSYNC look like HSYNC +                if (*(uint16_t*)(dataPtr) != HSYNC_PATTERN) +                { +                    // this means 0xFFFF followed by something else - invalid ID + ???? +                    throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_DFMTR_BAD_FHSYNC, m_trc_curr_idx, "Bad FSYNC pattern before frame or invalid ID.(0x7F)"); +                } +                else +                { +                    f_sync_bytes += 2; +                    buf_left -= 2; +                    dataPtr += 2; +                } +                m_b_fsync_start_eob = false; +            } + +            // regular fsync checks +            while ((buf_left >= 4) && (*((uint32_t*)(dataPtr)) == FSYNC_PATTERN))              {                  f_sync_bytes += 4;                  dataPtr += 4; -                cont_process = (bool)(dataPtr < eodPtr); +                buf_left -= 4;              } -        } -        // not an FSYNC -        while((m_ex_frm_n_bytes < OCSD_DFRMTR_FRAME_SIZE) && cont_process) -        { -            // check for illegal out of sequence FSYNC -            if((m_ex_frm_n_bytes % 4) == 0) +            // handle possible part fsync at the end of a buffer +            if (buf_left == 2)              { -                if(*((uint32_t *)(dataPtr)) == FSYNC_PATTERN)  +                if (*(uint16_t*)(dataPtr) == FSYNC_START)                  { -                    // throw an illegal FSYNC error -                    throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_DFMTR_BAD_FHSYNC, m_trc_curr_idx, "Bad FSYNC in frame."); +                    f_sync_bytes += 2; +                    buf_left -= 2; +                    dataPtr += 2; +                    m_b_fsync_start_eob = true;                  }              } +        } +        // process remaining data in pairs of bytes +        while ((m_ex_frm_n_bytes < OCSD_DFRMTR_FRAME_SIZE) && buf_left) +        {              // mark start of frame after FSyncs  -            if(m_ex_frm_n_bytes == 0) +            if (m_ex_frm_n_bytes == 0)                  m_trc_curr_idx_sof = m_trc_curr_idx + f_sync_bytes;              m_ex_frm_data[m_ex_frm_n_bytes] = dataPtr[0]; -            m_ex_frm_data[m_ex_frm_n_bytes+1] = dataPtr[1]; -            m_ex_frm_n_bytes+=2; -            ex_bytes +=2; +            m_ex_frm_data[m_ex_frm_n_bytes + 1] = dataPtr[1]; + +            data_pair_val = *((uint16_t*)(dataPtr));              // check pair is not HSYNC -            if(*((uint16_t *)(dataPtr)) == HSYNC_PATTERN) +            if (data_pair_val == HSYNC_PATTERN)              { -                if(hasHSyncs) +                if (hasHSyncs)                  { -                    m_ex_frm_n_bytes-=2; -                    ex_bytes -= 2; -                    h_sync_bytes+=2; +                    h_sync_bytes += 2;                  }                  else                  { @@ -564,22 +601,27 @@ bool TraceFmtDcdImpl::extractFrame()                      throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_DFMTR_BAD_FHSYNC, m_trc_curr_idx, "Bad HSYNC in frame.");                  }              } +            // can't have a start of FSYNC here / illegal trace ID +            else if (data_pair_val == FSYNC_START) +            { +                throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_DFMTR_BAD_FHSYNC, m_trc_curr_idx, "Bad FSYNC start in frame or invalid ID (0x7F)."); +            } +            else +            { +                m_ex_frm_n_bytes += 2; +                ex_bytes += 2; +            } +            buf_left -= 2;              dataPtr += 2; -            cont_process = (bool)(dataPtr < eodPtr);          } - -        // if we hit the end of data but still have a complete frame waiting,  -        // need to continue processing to allow it to be used. -        if(!cont_process && (m_ex_frm_n_bytes == OCSD_DFRMTR_FRAME_SIZE)) -            cont_process = true;      }      // total bytes processed this pass       uint32_t total_processed = ex_bytes + f_sync_bytes + h_sync_bytes;      // output raw data on raw frame channel - packed raw.  -    if (((m_ex_frm_n_bytes == OCSD_DFRMTR_FRAME_SIZE) || !cont_process) && m_b_output_packed_raw) +    if (((m_ex_frm_n_bytes == OCSD_DFRMTR_FRAME_SIZE) || (buf_left == 0)) && m_b_output_packed_raw)      {          outputRawMonBytes(  OCSD_OP_DATA,                               m_trc_curr_idx,  @@ -595,7 +637,11 @@ bool TraceFmtDcdImpl::extractFrame()      // update index past the processed data         m_trc_curr_idx += total_processed; -    return cont_process; +    // update any none trace data byte stats +    addToFrameStats((uint64_t)(f_sync_bytes + h_sync_bytes)); + +    // if we are exiting with a full frame then signal processing to continue +    return (bool)(m_ex_frm_n_bytes == OCSD_DFRMTR_FRAME_SIZE);  }  bool TraceFmtDcdImpl::unpackFrame() @@ -604,6 +650,7 @@ bool TraceFmtDcdImpl::unpackFrame()      uint8_t frameFlagBit = 0x1;      uint8_t newSrcID = OCSD_BAD_CS_SRC_ID;      bool PrevIDandIDChange = false; +    uint64_t noneDataBytes = 0;      // init output processing      m_out_data_idx = 0;    @@ -650,6 +697,7 @@ bool TraceFmtDcdImpl::unpackFrame()                  /// TBD - ID indexing in here.              } +            noneDataBytes++;          }          else          // it's just data @@ -671,6 +719,7 @@ bool TraceFmtDcdImpl::unpackFrame()      {          // no matter if change or not, no associated data in byte 15 anyway so just set.          m_curr_src_ID = (m_ex_frm_data[14] >> 1) & 0x7f; +        noneDataBytes++;      }      // it's data      else @@ -678,6 +727,9 @@ bool TraceFmtDcdImpl::unpackFrame()          m_out_data[m_out_data_idx].data[m_out_data[m_out_data_idx].valid++] = m_ex_frm_data[14] | ((frameFlagBit & m_ex_frm_data[15]) ? 0x1 : 0x0);       }      m_ex_frm_n_bytes = 0;   // mark frame as empty; + +    noneDataBytes++;    // byte 15 is always non-data. +    addToFrameStats(noneDataBytes); // update the non data byte stats.       return true;  } @@ -716,6 +768,8 @@ bool TraceFmtDcdImpl::outputFrame()                      m_out_data[m_out_processed].data + m_out_data[m_out_processed].used,                      &bytes_used));                +                addToIDStats((uint64_t)bytes_used); +                  if(!dataPathCont())                  {                      cont_processing = false; @@ -739,7 +793,12 @@ bool TraceFmtDcdImpl::outputFrame()                          m_out_data[m_out_processed].valid,                          m_out_data[m_out_processed].data,                          m_out_data[m_out_processed].id); -                }                 +                }   + +                if (isReservedID(m_out_data[m_out_processed].id)) +                    addToReservedIDStats((uint64_t)m_out_data[m_out_processed].valid); +                else +                    addToNoIDStats((uint64_t)m_out_data[m_out_processed].valid);                  m_out_processed++; // skip past this data.              }          } @@ -754,13 +813,44 @@ bool TraceFmtDcdImpl::outputFrame()                      m_out_data[m_out_processed].valid,                      m_out_data[m_out_processed].data,                      m_out_data[m_out_processed].id); -            }              +            }  +            addToUnknownIDStats((uint64_t)m_out_data[m_out_processed].valid);                          m_out_processed++; // skip past this data.          }      }      return cont_processing;  } +     +void TraceFmtDcdImpl::addToIDStats(uint64_t val) +{ +    if (m_pStatsBlock) +        m_pStatsBlock->valid_id_bytes += val; +} + +void TraceFmtDcdImpl::addToNoIDStats(uint64_t val) +{ +    if (m_pStatsBlock) +        m_pStatsBlock->no_id_bytes += val; +} + +void TraceFmtDcdImpl::addToFrameStats(uint64_t val) +{ +    if (m_pStatsBlock) +        m_pStatsBlock->frame_bytes += val; +} + +void TraceFmtDcdImpl::addToUnknownIDStats(uint64_t val) +{ +    if (m_pStatsBlock) +        m_pStatsBlock->unknown_id_bytes += val; +} +void TraceFmtDcdImpl::addToReservedIDStats(uint64_t val) +{ +    if (m_pStatsBlock) +        m_pStatsBlock->reserved_id_bytes += val; +} +   /***************************************************************/  /* interface */  /***************************************************************/ @@ -819,21 +909,27 @@ componentAttachPt<ITraceErrorLog> *TraceFormatterFrameDecoder::getErrLogAttachPt      return (m_pDecoder != 0) ? m_pDecoder->getErrorLogAttachPt() : 0;  } -/* configuration - set operational mode for incoming stream (has FSYNCS etc) */ -ocsd_err_t TraceFormatterFrameDecoder::Configure(uint32_t cfg_flags) +ocsd_err_t TraceFormatterFrameDecoder::Init()  { -    if(!m_pDecoder)  -    {   -        if(m_instNum >= 0) +    if (!m_pDecoder) +    { +        if (m_instNum >= 0)              m_pDecoder = new (std::nothrow) TraceFmtDcdImpl(m_instNum);          else              m_pDecoder = new (std::nothrow) TraceFmtDcdImpl(); -        if(!m_pDecoder) return OCSD_ERR_MEM; +        if (!m_pDecoder) return OCSD_ERR_MEM;      } -    m_pDecoder->DecodeConfigure(cfg_flags);      return OCSD_OK;  } +/* configuration - set operational mode for incoming stream (has FSYNCS etc) */ +ocsd_err_t TraceFormatterFrameDecoder::Configure(uint32_t cfg_flags) +{ +    if (!m_pDecoder) +        return OCSD_ERR_NOT_INIT; +    return m_pDecoder->DecodeConfigure(cfg_flags); +} +  const uint32_t TraceFormatterFrameDecoder::getConfigFlags() const  {      uint32_t flags = 0; @@ -865,5 +961,10 @@ ocsd_datapath_resp_t TraceFormatterFrameDecoder::Flush()      return (m_pDecoder == 0) ? OCSD_RESP_FATAL_NOT_INIT : m_pDecoder->Flush();  } +void TraceFormatterFrameDecoder::SetDemuxStatsBlock(ocsd_demux_stats_t *pStatsBlock) +{ +    if (m_pDecoder) +        m_pDecoder->SetDemuxStatsBlock(pStatsBlock); +}  /* End of File trc_frame_deformatter.cpp */ diff --git a/decoder/source/trc_frame_deformatter_impl.h b/decoder/source/trc_frame_deformatter_impl.h index e1fc17ab259f..3571d5f2fc47 100644 --- a/decoder/source/trc_frame_deformatter_impl.h +++ b/decoder/source/trc_frame_deformatter_impl.h @@ -75,6 +75,8 @@ private:      ocsd_err_t DecodeConfigure(uint32_t flags);      ocsd_err_t SetForcedSyncIndex(ocsd_trc_index_t index, bool bSet); +    void SetDemuxStatsBlock(ocsd_demux_stats_t *pStatsBlock) { m_pStatsBlock = pStatsBlock; }; +  private:      ocsd_datapath_resp_t executeNoneDataOpAllIDs(ocsd_datapath_op_t op, const ocsd_trc_index_t index = 0);      ocsd_datapath_resp_t processTraceData(const ocsd_trc_index_t index,  @@ -113,12 +115,20 @@ private:      void setRawChanFilterAll(bool bEnable);      const bool rawChanEnabled(const uint8_t id) const; -	int checkForResetFSyncPatterns(); +	ocsd_err_t checkForResetFSyncPatterns(uint32_t &f_sync_bytes);      friend class TraceFormatterFrameDecoder; -    // attachment points +    // stats updates +    void addToIDStats(uint64_t val); +    void addToNoIDStats(uint64_t val); +    void addToFrameStats(uint64_t val); +    void addToUnknownIDStats(uint64_t val); +    void addToReservedIDStats(uint64_t val); +     +    bool isReservedID(uint8_t ID) { return ((ID == 0) || (ID >= 0x70)); }; +    // attachment points      componentAttachPt<ITrcDataIn> m_IDStreams[128];      componentAttachPt<ITrcRawFrameIn> m_RawTraceFrame; @@ -142,12 +152,18 @@ private:      // incoming frame buffer       uint8_t m_ex_frm_data[OCSD_DFRMTR_FRAME_SIZE]; // buffer the current frame in case we have to stop part way through      int m_ex_frm_n_bytes;   // number of valid bytes in the current frame (extraction) +    bool m_b_fsync_start_eob;  // flag to indicate that the end of the last buffer was a pair of bytes +                               // (0xffff) that could only validly be the start and FSYNC.      ocsd_trc_index_t m_trc_curr_idx_sof; // trace source index at start of frame. -    // channel output data - can never be more than a frame of data for a single ID. -    out_chan_data m_out_data[7];  // can only be 8 ID changes in a frame, but last on has no associated data so 7 possible data blocks +    /* channel output data - can never be more than a frame of data for a single ID. +     * 8 possible ID changes per frame. Although the final one can have no associated data, a pathological +     * case exists with 7 ID changes, all data associated with a previous frame, except for last  +     * ID / data byte which is data. Not possible with normal hardware but guard against corrupt input. +     */ +    out_chan_data m_out_data[8]; // output data for a given ID      int m_out_data_idx;          // number of out_chan_data frames used. -    int m_out_processed;          // number of complete out_chan_data frames output. +    int m_out_processed;         // number of complete out_chan_data frames output.      /* local copy of input buffer pointers*/      const uint8_t *m_in_block_base; @@ -159,6 +175,8 @@ private:      bool m_b_output_unpacked_raw;      bool m_raw_chan_enable[128]; + +    ocsd_demux_stats_t *m_pStatsBlock;  }; diff --git a/decoder/source/trc_gen_elem.cpp b/decoder/source/trc_gen_elem.cpp index e1774203ebc5..c94c5a7c6848 100644 --- a/decoder/source/trc_gen_elem.cpp +++ b/decoder/source/trc_gen_elem.cpp @@ -54,7 +54,10 @@ static const char *s_elem_descs[][2] =      {"OCSD_GEN_TRC_ELEM_TIMESTAMP","Timestamp - preceding elements happeded before this time."},      {"OCSD_GEN_TRC_ELEM_CYCLE_COUNT","Cycle count - cycles since last cycle count value - associated with a preceding instruction range."},      {"OCSD_GEN_TRC_ELEM_EVENT","Event - numbered event or trigger"}, -    {"OCSD_GEN_TRC_ELEM_SWTRACE","Software trace packet - may contain data payload."}, +    {"OCSD_GEN_TRC_ELEM_SWTRACE","Software trace packet - may contain data payload. STM / ITM hardware trace with channel protocol."}, +    {"OCSD_GEN_TRC_ELEM_SYNC_MARKER","Synchronisation marker - marks position in stream of an element that is output later."}, +    {"OCSD_GEN_TRC_ELEM_MEMTRANS","Trace indication of transactional memory operations."}, +    {"OCSD_GEN_TRC_ELEM_INSTRUMENTATION", "PE instrumentation trace - PE generated SW trace, application dependent protocol."},      {"OCSD_GEN_TRC_ELEM_CUSTOM","Fully custom packet type."}  }; @@ -64,7 +67,8 @@ static const char *instr_type[] = {      "iBR ",      "ISB ",      "DSB.DMB", -    "WFI.WFE" +    "WFI.WFE", +    "TSTART"  };  #define T_SIZE (sizeof(instr_type) / sizeof(const char *)) @@ -105,6 +109,16 @@ static const char *s_unsync_reason[] = {      "bad-packet",           // UNSYNC_BAD_PACKET - bad packet at input - resync to restart.      "end-of-trace",         // UNSYNC_EOT - end of trace info.  }; +static const char *s_transaction_type[] = { +	"Init", +    "Start", +    "Commit", +    "Fail" +}; + +static const char *s_marker_t[] = { +  "Timestamp marker",  //  ELEM_MARKER_TS   +};  void OcsdTraceElement::toString(std::string &str) const  { @@ -158,7 +172,14 @@ void OcsdTraceElement::toString(std::string &str) const              {                  oss << "EL" << std::dec << (int)(context.exception_level);              } -            oss << (context.security_level == ocsd_sec_secure ? "S; " : "N; ") << (context.bits64 ? "64-bit; " : "32-bit; "); +            switch (context.security_level)  +            { +            case ocsd_sec_secure: oss << "S; "; break; +            case ocsd_sec_nonsecure: oss << "N; "; break; +            case ocsd_sec_root: oss << "Root; "; break; +            case ocsd_sec_realm: oss << "Realm; "; break; +            } +            oss  << (context.bits64 ? "64-bit; " : "32-bit; ");              if(context.vmid_valid)                  oss << "VMID=0x" << std::hex << context.vmid << "; ";              if(context.ctxt_id_valid) @@ -190,6 +211,19 @@ void OcsdTraceElement::toString(std::string &str) const                  oss << " [" << s_unsync_reason[unsync_eot_info] << "]";              break; +        case OCSD_GEN_TRC_ELEM_SYNC_MARKER: +            oss << " [" << s_marker_t[sync_marker.type] << "(0x" << std::setfill('0') << std::setw(8) << std::hex << sync_marker.value << ")]"; +            break; + +        case OCSD_GEN_TRC_ELEM_MEMTRANS: +            if (mem_trans <= OCSD_MEM_TRANS_FAIL) +                oss << s_transaction_type[mem_trans]; +            break; + +        case OCSD_GEN_TRC_ELEM_INSTRUMENTATION: +            oss << "EL" << std::dec << (int)sw_ite.el << "; 0x" << std::setfill('0') << std::setw(16) << std::hex << sw_ite.value; +            break; +          default: break;          }          if(has_cc) diff --git a/decoder/source/trc_printable_elem.cpp b/decoder/source/trc_printable_elem.cpp index 88c7bb226f41..2b60c030d53f 100644 --- a/decoder/source/trc_printable_elem.cpp +++ b/decoder/source/trc_printable_elem.cpp @@ -52,8 +52,6 @@ void trcPrintableElem::getValStr(std::string &valStr, const int valTotalBitSize,      assert((valTotalBitSize >= 4) && (valTotalBitSize <= 64)); -    uint64_t LimitMask = ~0ULL; -    LimitMask >>= 64-valTotalBitSize;      valStr = "0x";      if(asHex)  | 
