aboutsummaryrefslogtreecommitdiff
path: root/decoder/source
diff options
context:
space:
mode:
Diffstat (limited to 'decoder/source')
-rw-r--r--decoder/source/c_api/ocsd_c_api.cpp51
-rw-r--r--decoder/source/ete/trc_cmp_cfg_ete.cpp98
-rw-r--r--decoder/source/etmv3/trc_pkt_elem_etmv3.cpp2
-rw-r--r--decoder/source/etmv4/trc_cmp_cfg_etmv4.cpp2
-rw-r--r--decoder/source/etmv4/trc_etmv4_stack_elem.cpp38
-rw-r--r--decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp680
-rw-r--r--decoder/source/etmv4/trc_pkt_elem_etmv4i.cpp86
-rw-r--r--decoder/source/etmv4/trc_pkt_proc_etmv4i.cpp158
-rw-r--r--decoder/source/i_dec/trc_i_decode.cpp17
-rw-r--r--decoder/source/i_dec/trc_idec_arminst.cpp30
-rw-r--r--decoder/source/mem_acc/trc_mem_acc_mapper.cpp8
-rw-r--r--decoder/source/ocsd_dcd_tree.cpp79
-rw-r--r--decoder/source/ocsd_error.cpp21
-rw-r--r--decoder/source/ocsd_gen_elem_stack.cpp1
-rw-r--r--decoder/source/ocsd_lib_dcd_register.cpp5
-rw-r--r--decoder/source/pkt_printers/trc_print_fact.cpp3
-rw-r--r--decoder/source/ptm/trc_pkt_proc_ptm.cpp7
-rw-r--r--decoder/source/trc_core_arch_map.cpp104
-rw-r--r--decoder/source/trc_frame_deformatter.cpp259
-rw-r--r--decoder/source/trc_frame_deformatter_impl.h28
-rw-r--r--decoder/source/trc_gen_elem.cpp40
-rw-r--r--decoder/source/trc_printable_elem.cpp2
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)