aboutsummaryrefslogtreecommitdiff
path: root/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp')
-rw-r--r--decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp680
1 files changed, 541 insertions, 139 deletions
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[] = {