2 * \file trc_pkt_decode_etmv4i.cpp
3 * \brief OpenCSD : ETMv4 decoder
5 * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved.
10 * Redistribution and use in source and binary forms, with or without modification,
11 * are permitted provided that the following conditions are met:
13 * 1. Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright notice,
17 * this list of conditions and the following disclaimer in the documentation
18 * and/or other materials provided with the distribution.
20 * 3. Neither the name of the copyright holder nor the names of its contributors
21 * may be used to endorse or promote products derived from this software without
22 * specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include "opencsd/etmv4/trc_pkt_decode_etmv4i.h"
38 #include "common/trc_gen_elem.h"
41 #define DCD_NAME "DCD_ETMV4"
43 static const uint32_t ETMV4_SUPPORTED_DECODE_OP_FLAGS = OCSD_OPFLG_PKTDEC_COMMON;
45 TrcPktDecodeEtmV4I::TrcPktDecodeEtmV4I()
46 : TrcPktDecodeBase(DCD_NAME)
51 TrcPktDecodeEtmV4I::TrcPktDecodeEtmV4I(int instIDNum)
52 : TrcPktDecodeBase(DCD_NAME,instIDNum)
57 TrcPktDecodeEtmV4I::~TrcPktDecodeEtmV4I()
61 /*********************** implementation packet decoding interface */
63 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processPacket()
65 ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
66 bool bPktDone = false;
73 // output the initial not synced packet to the sink
74 m_output_elem.setType(OCSD_GEN_TRC_ELEM_NO_SYNC);
75 resp = outputTraceElement(m_output_elem);
76 m_curr_state = WAIT_SYNC;
77 // fall through to check if the current packet is the async we are waiting for.
81 if(m_curr_packet_in->getType() == ETM4_PKT_I_ASYNC)
82 m_curr_state = WAIT_TINFO;
89 if(m_curr_packet_in->getType() == ETM4_PKT_I_TRACE_INFO)
92 m_curr_state = DECODE_PKTS;
93 m_return_stack.flush();
99 resp = decodePacket(bPktDone); // this may change the state to commit elem;
103 resp = commitElements(bPktDone); // this will change the state to DECODE_PKTS once all elem committed.
111 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::onEOT()
113 ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
119 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::onReset()
121 ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
126 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::onFlush()
128 ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
130 // continue exception processing (can't go through processPacket as elements no longer on stack)
131 if(m_excep_proc != EXCEP_POP)
132 resp = processException();
133 // continue ongoing output operations on comitted elements.
134 else if(m_curr_state == COMMIT_ELEM)
135 resp = processPacket();
136 // continue flushing at end of trace
142 ocsd_err_t TrcPktDecodeEtmV4I::onProtocolConfig()
144 ocsd_err_t err = OCSD_OK;
146 // set some static config elements
147 m_CSID = m_config->getTraceID();
148 m_max_spec_depth = m_config->MaxSpecDepth();
149 m_p0_key_max = m_config->P0_Key_Max();
150 m_cond_key_max_incr = m_config->CondKeyMaxIncr();
152 // set up static trace instruction decode elements
153 m_instr_info.dsb_dmb_waypoints = 0;
154 m_instr_info.pe_type.arch = m_config->archVersion();
155 m_instr_info.pe_type.profile = m_config->coreProfile();
157 m_IASize64 = (m_config->iaSizeMax() == 64);
159 if (m_config->enabledRetStack())
161 m_return_stack.set_active(true);
162 #ifdef TRC_RET_STACK_DEBUG
163 m_return_stack.set_dbg_logger(this);
167 // check config compatible with current decoder support level.
168 // at present no data trace, no spec depth, no return stack, no QE
169 // Remove these checks as support is added.
170 if(m_max_spec_depth != 0)
172 err = OCSD_ERR_HW_CFG_UNSUPP;
173 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : None-zero speculation depth not supported"));
175 else if(m_config->enabledDataTrace())
177 err = OCSD_ERR_HW_CFG_UNSUPP;
178 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : Data trace elements not supported"));
180 else if(m_config->enabledLSP0Trace())
182 err = OCSD_ERR_HW_CFG_UNSUPP;
183 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : LSP0 elements not supported."));
185 else if(m_config->enabledCondITrace() != EtmV4Config::COND_TR_DIS)
187 err = OCSD_ERR_HW_CFG_UNSUPP;
188 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : Trace on conditional non-branch elements not supported."));
190 else if(m_config->enabledQE())
192 err = OCSD_ERR_HW_CFG_UNSUPP;
193 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : Trace using Q elements not supported."));
199 /************* local decode methods */
200 void TrcPktDecodeEtmV4I::initDecoder()
202 // set the operational modes supported.
203 m_supported_op_flags = ETMV4_SUPPORTED_DECODE_OP_FLAGS;
205 /* init elements that get set by config */
206 m_max_spec_depth = 0;
209 m_cond_key_max_incr = 0;
212 // reset decoder state to unsynced
216 void TrcPktDecodeEtmV4I::resetDecoder()
218 m_curr_state = NO_SYNC;
225 m_curr_spec_depth = 0;
231 m_except_pending_addr = false;
232 m_mem_nacc_pending = false;
233 m_prev_overflow = false;
234 m_P0_stack.delete_all();
235 m_output_elem.init();
236 m_excep_proc = EXCEP_POP;
240 // this function can output an immediate generic element if this covers the complete packet decode,
241 // or stack P0 and other elements for later processing on commit or cancel.
242 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::decodePacket(bool &Complete)
244 bool bAllocErr = false;
245 ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
247 bool is_addr = false;
248 bool is_except = false;
250 switch(m_curr_packet_in->getType())
252 case ETM4_PKT_I_ASYNC: // nothing to do with this packet.
255 case ETM4_PKT_I_TRACE_INFO:
256 // skip subsequent TInfo packets.
257 m_return_stack.flush();
260 case ETM4_PKT_I_TRACE_ON:
262 if (m_P0_stack.createParamElemNoParam(P0_TRC_ON, false, m_curr_packet_in->getType(), m_index_curr_pkt) == 0)
267 case ETM4_PKT_I_OVERFLOW:
269 if (m_P0_stack.createParamElemNoParam(P0_OVERFLOW, false, m_curr_packet_in->getType(), m_index_curr_pkt) == 0)
274 case ETM4_PKT_I_ATOM_F1:
275 case ETM4_PKT_I_ATOM_F2:
276 case ETM4_PKT_I_ATOM_F3:
277 case ETM4_PKT_I_ATOM_F4:
278 case ETM4_PKT_I_ATOM_F5:
279 case ETM4_PKT_I_ATOM_F6:
281 if (m_P0_stack.createAtomElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getAtom()) == 0)
284 m_curr_spec_depth += m_curr_packet_in->getAtom().num;
288 case ETM4_PKT_I_CTXT:
290 if (m_P0_stack.createContextElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getContext()) == 0)
295 case ETM4_PKT_I_ADDR_MATCH:
297 etmv4_addr_val_t addr;
299 addr.val = m_curr_packet_in->getAddrVal();
300 addr.isa = m_curr_packet_in->getAddrIS();
301 if (m_P0_stack.createAddrElem(m_curr_packet_in->getType(), m_index_curr_pkt, addr) == 0)
307 case ETM4_PKT_I_ADDR_CTXT_L_64IS0:
308 case ETM4_PKT_I_ADDR_CTXT_L_64IS1:
309 case ETM4_PKT_I_ADDR_CTXT_L_32IS0:
310 case ETM4_PKT_I_ADDR_CTXT_L_32IS1:
312 if (m_P0_stack.createContextElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getContext()) == 0)
315 case ETM4_PKT_I_ADDR_L_32IS0:
316 case ETM4_PKT_I_ADDR_L_32IS1:
317 case ETM4_PKT_I_ADDR_L_64IS0:
318 case ETM4_PKT_I_ADDR_L_64IS1:
319 case ETM4_PKT_I_ADDR_S_IS0:
320 case ETM4_PKT_I_ADDR_S_IS1:
322 etmv4_addr_val_t addr;
324 addr.val = m_curr_packet_in->getAddrVal();
325 addr.isa = m_curr_packet_in->getAddrIS();
326 if (m_P0_stack.createAddrElem(m_curr_packet_in->getType(), m_index_curr_pkt, addr) == 0)
333 case ETM4_PKT_I_EXCEPT:
335 if (m_P0_stack.createExceptElem(m_curr_packet_in->getType(), m_index_curr_pkt,
336 (m_curr_packet_in->exception_info.addr_interp == 0x2),
337 m_curr_packet_in->exception_info.exceptionType) == 0)
341 m_except_pending_addr = true; // wait for following packets before marking for commit.
347 case ETM4_PKT_I_EXCEPT_RTN:
349 // P0 element if V7M profile.
350 bool bV7MProfile = (m_config->archVersion() == ARCH_V7) && (m_config->coreProfile() == profile_CortexM);
351 if (m_P0_stack.createParamElemNoParam(P0_EXCEP_RET, bV7MProfile, m_curr_packet_in->getType(), m_index_curr_pkt) == 0)
357 case ETM4_PKT_I_EVENT:
359 std::vector<uint32_t> params = { 0 };
360 params[0] = (uint32_t)m_curr_packet_in->event_val;
361 if (m_P0_stack.createParamElem(P0_EVENT, false, m_curr_packet_in->getType(), m_index_curr_pkt, params) == 0)
367 /* cycle count packets */
368 case ETM4_PKT_I_CCNT_F1:
369 case ETM4_PKT_I_CCNT_F2:
370 case ETM4_PKT_I_CCNT_F3:
372 std::vector<uint32_t> params = { 0 };
373 params[0] = m_curr_packet_in->getCC();
374 if (m_P0_stack.createParamElem(P0_EVENT, false, m_curr_packet_in->getType(), m_index_curr_pkt, params) == 0)
381 case ETM4_PKT_I_TIMESTAMP:
383 bool bTSwithCC = m_config->enabledCCI();
384 uint64_t ts = m_curr_packet_in->getTS();
385 std::vector<uint32_t> params = { 0, 0, 0 };
386 params[0] = (uint32_t)(ts & 0xFFFFFFFF);
387 params[1] = (uint32_t)((ts >> 32) & 0xFFFFFFFF);
389 params[2] = m_curr_packet_in->getCC();
390 if (m_P0_stack.createParamElem(P0_EVENT, false, m_curr_packet_in->getType(), m_index_curr_pkt, params) == 0)
396 case ETM4_PKT_I_BAD_SEQUENCE:
397 resp = handleBadPacket("Bad byte sequence in packet.");
400 case ETM4_PKT_I_BAD_TRACEMODE:
401 resp = handleBadPacket("Invalid packet type for trace mode.");
404 case ETM4_PKT_I_RESERVED:
405 resp = handleBadPacket("Reserved packet header");
408 /*** presently unsupported packets ***/
409 /* conditional instruction tracing */
410 case ETM4_PKT_I_COND_FLUSH:
411 case ETM4_PKT_I_COND_I_F1:
412 case ETM4_PKT_I_COND_I_F2:
413 case ETM4_PKT_I_COND_I_F3:
414 case ETM4_PKT_I_COND_RES_F1:
415 case ETM4_PKT_I_COND_RES_F2:
416 case ETM4_PKT_I_COND_RES_F3:
417 case ETM4_PKT_I_COND_RES_F4:
419 case ETM4_PKT_I_CANCEL_F1:
420 case ETM4_PKT_I_CANCEL_F2:
421 case ETM4_PKT_I_CANCEL_F3:
422 case ETM4_PKT_I_COMMIT:
423 case ETM4_PKT_I_MISPREDICT:
424 case ETM4_PKT_I_DISCARD:
425 // data synchronisation markers
426 case ETM4_PKT_I_NUM_DS_MKR:
427 case ETM4_PKT_I_UNNUM_DS_MKR:
430 resp = OCSD_RESP_FATAL_INVALID_DATA;
431 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_DECODE_PKT,"Unsupported packet type."));
435 // any other packet - bad packet error
436 resp = OCSD_RESP_FATAL_INVALID_DATA;
437 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_DECODE_PKT,"Unknown packet type."));
442 // we need to wait for following address after exception
443 // - work out if we have seen enough here...
444 if(m_except_pending_addr && !is_except)
446 m_except_pending_addr = false; //next packet has to be an address
447 // exception packet sequence complete
450 m_curr_spec_depth++; // exceptions are P0 elements so up the spec depth to commit if needed.
454 resp = OCSD_RESP_FATAL_INVALID_DATA;
455 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_DECODE_PKT,"Expected Address packet to follow exception packet."));
461 resp = OCSD_RESP_FATAL_SYS_ERR;
462 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_MEM,"Memory allocation error."));
464 else if(m_curr_spec_depth > m_max_spec_depth)
466 // auto commit anything above max spec depth
467 // (this will auto commit anything if spec depth not supported!)
468 m_P0_commit = m_curr_spec_depth - m_max_spec_depth;
469 m_curr_state = COMMIT_ELEM;
470 Complete = false; // force the processing of the commit elements.
475 void TrcPktDecodeEtmV4I::doTraceInfoPacket()
477 m_trace_info = m_curr_packet_in->getTraceInfo();
478 m_cc_threshold = m_curr_packet_in->getCCThreshold();
479 m_p0_key = m_curr_packet_in->getP0Key();
480 m_curr_spec_depth = m_curr_packet_in->getCurrSpecDepth();
484 * Walks through the element stack, processing from oldest element to the newest,
485 according to the number of P0 elements that need committing.
487 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::commitElements(bool &Complete)
489 ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
490 bool bPause = false; // pause commit operation
491 bool bPopElem = true; // do we remove the element from the stack (multi atom elements may need to stay!)
492 int num_commit_req = m_P0_commit;
494 Complete = true; // assume we exit due to completion of commit operation
496 TrcStackElem *pElem = 0; // stacked element pointer
498 while(m_P0_commit && !bPause)
500 if(m_P0_stack.size() > 0)
502 pElem = m_P0_stack.back(); // get oldest element
504 switch(pElem->getP0Type())
506 // indicates a trace restart - beginning of trace or discontinuiuty
508 m_output_elem.setType(OCSD_GEN_TRC_ELEM_TRACE_ON);
509 m_output_elem.trace_on_reason = m_prev_overflow ? TRACE_ON_OVERFLOW : TRACE_ON_NORMAL;
510 m_prev_overflow = false;
511 resp = outputTraceElementIdx(pElem->getRootIndex(),m_output_elem);
512 m_return_stack.flush();
517 TrcStackElemAddr *pAddrElem = dynamic_cast<TrcStackElemAddr *>(pElem);
518 m_return_stack.clear_pop_pending(); // address removes the need to pop the indirect address target from the stack
521 SetInstrInfoInAddrISA(pAddrElem->getAddr().val, pAddrElem->getAddr().isa);
529 TrcStackElemCtxt *pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem);
532 etmv4_context_t ctxt = pCtxtElem->getContext();
533 // check this is an updated context
536 updateContext(pCtxtElem);
538 m_output_elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT);
539 resp = outputTraceElementIdx(pElem->getRootIndex(),m_output_elem);
547 TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
549 resp = this->outputEvent(pParamElem);
555 TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
557 resp = outputTS(pParamElem,false);
563 TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
565 resp = outputCC(pParamElem);
571 TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
573 resp = outputTS(pParamElem,true);
578 m_prev_overflow = true;
583 TrcStackElemAtom *pAtomElem = dynamic_cast<TrcStackElemAtom *>(pElem);
587 bool bContProcess = true;
588 while(!pAtomElem->isEmpty() && m_P0_commit && bContProcess)
590 ocsd_atm_val atom = pAtomElem->commitOldest();
592 // check if prev atom left us an indirect address target on the return stack
593 if ((resp = returnStackPop()) != OCSD_RESP_CONT)
596 // if address and context do instruction trace follower.
597 // otherwise skip atom and reduce committed elements
598 if(!m_need_ctxt && !m_need_addr)
600 resp = processAtom(atom,bContProcess);
602 m_P0_commit--; // mark committed
604 if(!pAtomElem->isEmpty())
605 bPopElem = false; // don't remove if still atoms to process.
611 // check if prev atom left us an indirect address target on the return stack
612 if ((resp = returnStackPop()) != OCSD_RESP_CONT)
615 m_excep_proc = EXCEP_POP; // set state in case we need to stop part way through
616 resp = processException(); // output trace + exception elements.
621 m_output_elem.setType(OCSD_GEN_TRC_ELEM_EXCEPTION_RET);
622 resp = outputTraceElementIdx(pElem->getRootIndex(),m_output_elem);
623 if(pElem->isP0()) // are we on a core that counts ERET as P0?
629 m_P0_stack.delete_back(); // remove element from stack;
631 // if response not continue, then break out of the loop.
632 if(!OCSD_DATA_RESP_IS_CONT(resp))
639 // too few elements for commit operation - decode error.
640 ocsd_trc_index_t err_idx = 0;
642 err_idx = pElem->getRootIndex();
644 resp = OCSD_RESP_FATAL_INVALID_DATA;
645 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_COMMIT_PKT_OVERRUN,err_idx,m_CSID,"Not enough elements to commit"));
650 // done all elements - need more packets.
652 m_curr_state = DECODE_PKTS;
654 // reduce the spec depth by number of comitted elements
655 m_curr_spec_depth -= (num_commit_req-m_P0_commit);
659 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::returnStackPop()
661 ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
664 if (m_return_stack.pop_pending())
666 ocsd_vaddr_t popAddr = m_return_stack.pop(nextISA);
667 if (m_return_stack.overflow())
669 resp = OCSD_RESP_FATAL_INVALID_DATA;
670 LogError(ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_RET_STACK_OVERFLOW, "Trace Return Stack Overflow."));
674 m_instr_info.instr_addr = popAddr;
675 m_instr_info.isa = nextISA;
682 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::flushEOT()
684 ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
687 TrcStackElem *pElem = 0;
688 while(OCSD_DATA_RESP_IS_CONT(resp) && (m_P0_stack.size() > 0))
690 // scan for outstanding events, TS and CC, before any outstanding
691 // P0 commit elements.
692 pElem = m_P0_stack.back();
694 switch(pElem->getP0Type())
696 // clear stack and stop
703 m_P0_stack.delete_all();
714 TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
716 resp = this->outputEvent(pParamElem);
722 TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
724 resp = outputTS(pParamElem,false);
730 TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
732 resp = outputCC(pParamElem);
738 TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
740 resp = outputTS(pParamElem,true);
744 m_P0_stack.delete_back();
747 if(OCSD_DATA_RESP_IS_CONT(resp) && (m_P0_stack.size() == 0))
749 m_output_elem.setType(OCSD_GEN_TRC_ELEM_EO_TRACE);
750 resp = outputTraceElement(m_output_elem);
757 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::outputCC(TrcStackElemParam *pParamElem)
759 m_output_elem.setType(OCSD_GEN_TRC_ELEM_CYCLE_COUNT);
760 m_output_elem.cycle_count = pParamElem->getParam(0);
761 return outputTraceElementIdx(pParamElem->getRootIndex(),m_output_elem);
764 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::outputTS(TrcStackElemParam *pParamElem, bool withCC)
766 m_output_elem.setType(OCSD_GEN_TRC_ELEM_TIMESTAMP);
767 m_output_elem.timestamp = (uint64_t)(pParamElem->getParam(0)) | (((uint64_t)pParamElem->getParam(1)) << 32);
769 m_output_elem.setCycleCount(pParamElem->getParam(2));
770 return outputTraceElementIdx(pParamElem->getRootIndex(),m_output_elem);
773 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::outputEvent(TrcStackElemParam *pParamElem)
775 m_output_elem.setType(OCSD_GEN_TRC_ELEM_EVENT);
776 m_output_elem.trace_event.ev_type = EVENT_NUMBERED;
777 m_output_elem.trace_event.ev_number = pParamElem->getParam(0);
778 return outputTraceElementIdx(pParamElem->getRootIndex(),m_output_elem);
781 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom, bool &bCont)
783 ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
784 TrcStackElem *pElem = m_P0_stack.back(); // get the atom element
785 bool bWPFound = false;
789 err = traceInstrToWP(bWPFound);
792 if(err == OCSD_ERR_UNSUPPORTED_ISA)
796 LogError(ocsdError(OCSD_ERR_SEV_WARN,err,pElem->getRootIndex(),m_CSID,"Warning: unsupported instruction set processing atom packet."));
797 // wait for next context
803 resp = OCSD_RESP_FATAL_INVALID_DATA;
804 LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,pElem->getRootIndex(),m_CSID,"Error processing atom packet."));
811 // save recorded next instuction address
812 ocsd_vaddr_t nextAddr = m_instr_info.instr_addr;
814 // action according to waypoint type and atom value
815 switch(m_instr_info.type)
820 m_instr_info.instr_addr = m_instr_info.branch_addr;
821 if (m_instr_info.is_link)
822 m_return_stack.push(nextAddr, m_instr_info.isa);
827 case OCSD_INSTR_BR_INDIRECT:
830 m_need_addr = true; // indirect branch taken - need new address.
831 if (m_instr_info.is_link)
832 m_return_stack.push(nextAddr,m_instr_info.isa);
833 m_return_stack.set_pop_pending(); // need to know next packet before we know what is to happen
837 m_output_elem.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE);
838 m_output_elem.setLastInstrInfo((atom == ATOM_E),m_instr_info.type, m_instr_info.sub_type);
839 m_output_elem.setISA(m_instr_info.isa);
840 resp = outputTraceElementIdx(pElem->getRootIndex(),m_output_elem);
845 // no waypoint - likely inaccessible memory range.
846 m_need_addr = true; // need an address update
848 if(m_output_elem.st_addr != m_output_elem.en_addr)
850 // some trace before we were out of memory access range
851 m_output_elem.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE);
852 m_output_elem.setLastInstrInfo(true,m_instr_info.type, m_instr_info.sub_type);
853 m_output_elem.setISA(m_instr_info.isa);
854 resp = outputTraceElementIdx(pElem->getRootIndex(),m_output_elem);
857 if(m_mem_nacc_pending && OCSD_DATA_RESP_IS_CONT(resp))
859 m_output_elem.setType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
860 m_output_elem.st_addr = m_nacc_addr;
861 resp = outputTraceElementIdx(pElem->getRootIndex(),m_output_elem);
862 m_mem_nacc_pending = false;
866 if(!OCSD_DATA_RESP_IS_CONT(resp))
872 // Exception processor
873 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processException()
875 ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
876 bool excep_implied_P0 = false; //!< exception implies P0
878 if(m_excep_proc == EXCEP_POP)
880 TrcStackElemExcept *pExceptElem = dynamic_cast<TrcStackElemExcept *>(m_P0_stack.back()); // get the exception element
881 TrcStackElemAddr *pAddressElem = 0;
882 TrcStackElemCtxt *pCtxtElem = 0;
883 TrcStackElem *pElem = 0;
885 m_P0_stack.pop_back(); // remove the exception element
886 pElem = m_P0_stack.back(); // look at next element.
887 if(pElem->getP0Type() == P0_CTXT)
889 pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem);
890 m_P0_stack.pop_back(); // remove the context element
891 pElem = m_P0_stack.back(); // next one should be an address element
894 if(pElem->getP0Type() != P0_ADDR)
896 // no following address element - indicate processing error.
897 resp = OCSD_RESP_FATAL_INVALID_DATA;
898 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,pExceptElem->getRootIndex(),m_CSID,"Address missing in exception packet."));
903 pAddressElem = static_cast<TrcStackElemAddr *>(pElem);
905 m_excep_addr = pAddressElem->getAddr();
907 // if we have context, get that.
909 updateContext(pCtxtElem);
911 // record the exception number
912 m_output_elem.exception_number = pExceptElem->getExcepNum();
914 // see if there is an implied P0 element on the exception.
915 excep_implied_P0 = pExceptElem->getPrevSame();
917 // save the trace index.
918 m_excep_index = pExceptElem->getRootIndex();
920 // figure out next move
921 if(m_excep_addr.val == m_instr_info.instr_addr)
922 m_excep_proc = EXCEP_EXCEP;
924 m_excep_proc = EXCEP_RANGE;
926 m_P0_stack.delete_popped();
929 // output a range element
930 if(m_excep_proc == EXCEP_RANGE)
932 bool bWPFound = false;
935 // last instr_info address is the start address
936 m_output_elem.st_addr = m_instr_info.instr_addr;
938 // look for either a WP or match to return address.
939 err = traceInstrToWP(bWPFound,!excep_implied_P0,m_excep_addr.val);
943 if(err == OCSD_ERR_UNSUPPORTED_ISA)
947 LogError(ocsdError(OCSD_ERR_SEV_WARN,err,m_excep_index,m_CSID,"Warning: unsupported instruction set processing exception packet."));
951 resp = OCSD_RESP_FATAL_INVALID_DATA;
952 LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,m_excep_index,m_CSID,"Error processing exception packet."));
953 m_excep_proc = EXCEP_POP; // nothing more to do, reset to start of exception handling
959 // action according to waypoint type and atom value
962 switch(m_instr_info.type)
965 m_instr_info.instr_addr = m_instr_info.branch_addr;
968 case OCSD_INSTR_BR_INDIRECT:
969 m_instr_info.instr_addr = m_excep_addr.val;
973 m_output_elem.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE);
974 m_output_elem.setLastInstrInfo(true,m_instr_info.type, m_instr_info.sub_type);
975 m_output_elem.setISA(m_instr_info.isa);
976 resp = outputTraceElementIdx(m_excep_index, m_output_elem);
977 m_excep_proc = EXCEP_EXCEP;
981 // no waypoint - likely inaccessible memory range.
982 m_need_addr = true; // need an address update
984 if(m_output_elem.st_addr != m_output_elem.en_addr)
986 // some trace before we were out of memory access range
987 m_output_elem.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE);
988 m_output_elem.setLastInstrInfo(true,m_instr_info.type, m_instr_info.sub_type);
989 m_output_elem.setISA(m_instr_info.isa);
990 resp = outputTraceElementIdx(m_excep_index,m_output_elem);
993 m_excep_proc = m_mem_nacc_pending ? EXCEP_NACC : EXCEP_EXCEP;
997 if((m_excep_proc == EXCEP_NACC) && OCSD_DATA_RESP_IS_CONT(resp))
999 m_output_elem.setType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
1000 m_output_elem.st_addr = m_nacc_addr;
1001 resp = outputTraceElementIdx(m_excep_index,m_output_elem);
1002 m_excep_proc = EXCEP_EXCEP;
1003 m_mem_nacc_pending = false;
1006 if((m_excep_proc == EXCEP_EXCEP) && OCSD_DATA_RESP_IS_CONT(resp))
1009 m_output_elem.setType(OCSD_GEN_TRC_ELEM_EXCEPTION);
1010 // add end address as preferred return address to end addr in element
1011 m_output_elem.en_addr = m_excep_addr.val;
1012 m_output_elem.excep_ret_addr = 1;
1013 resp = outputTraceElementIdx(m_excep_index,m_output_elem);
1014 m_excep_proc = EXCEP_POP;
1019 void TrcPktDecodeEtmV4I::SetInstrInfoInAddrISA(const ocsd_vaddr_t addr_val, const uint8_t isa)
1021 m_instr_info.instr_addr = addr_val;
1023 m_instr_info.isa = ocsd_isa_aarch64;
1025 m_instr_info.isa = (isa == 0) ? ocsd_isa_arm : ocsd_isa_thumb2;
1028 // trace an instruction range to a waypoint - and set next address to restart from.
1029 ocsd_err_t TrcPktDecodeEtmV4I::traceInstrToWP(bool &bWPFound, const bool traceToAddrNext /*= false*/, const ocsd_vaddr_t nextAddrMatch /*= 0*/)
1033 ocsd_err_t err = OCSD_OK;
1035 // TBD?: update mem space to allow for EL as well.
1036 ocsd_mem_space_acc_t mem_space = m_is_secure ? OCSD_MEM_SPACE_S : OCSD_MEM_SPACE_N;
1038 m_output_elem.st_addr = m_output_elem.en_addr = m_instr_info.instr_addr;
1042 while(!bWPFound && !m_mem_nacc_pending)
1044 // start off by reading next opcode;
1046 err = accessMemory(m_instr_info.instr_addr,mem_space,&bytesReq,(uint8_t *)&opcode);
1047 if(err != OCSD_OK) break;
1049 if(bytesReq == 4) // got data back
1051 m_instr_info.opcode = opcode;
1052 err = instrDecode(&m_instr_info);
1053 if(err != OCSD_OK) break;
1055 // increment address - may be adjusted by direct branch value later
1056 m_instr_info.instr_addr += m_instr_info.instr_size;
1058 // update the range decoded address in the output packet.
1059 m_output_elem.en_addr = m_instr_info.instr_addr;
1061 // either walking to match the next instruction address or a real watchpoint
1063 bWPFound = (m_output_elem.en_addr == nextAddrMatch);
1065 bWPFound = (m_instr_info.type != OCSD_INSTR_OTHER);
1069 // not enough memory accessible.
1070 m_mem_nacc_pending = true;
1071 m_nacc_addr = m_instr_info.instr_addr;
1077 void TrcPktDecodeEtmV4I::updateContext(TrcStackElemCtxt *pCtxtElem)
1079 etmv4_context_t ctxt = pCtxtElem->getContext();
1080 // map to output element and local saved state.
1081 m_is_64bit = (ctxt.SF != 0);
1082 m_output_elem.context.bits64 = ctxt.SF;
1083 m_is_secure = (ctxt.NS == 0);
1084 m_output_elem.context.security_level = ctxt.NS ? ocsd_sec_nonsecure : ocsd_sec_secure;
1085 m_output_elem.context.exception_level = (ocsd_ex_level)ctxt.EL;
1086 m_output_elem.context.el_valid = 1;
1089 m_output_elem.context.ctxt_id_valid = 1;
1090 m_context_id = m_output_elem.context.context_id = ctxt.ctxtID;
1094 m_output_elem.context.vmid_valid = 1;
1095 m_vmid_id = m_output_elem.context.vmid = ctxt.VMID;
1097 m_need_ctxt = false;
1100 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::handleBadPacket(const char *reason)
1102 ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
1104 if(getComponentOpMode() && OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS)
1106 // error out - stop decoding
1107 resp = OCSD_RESP_FATAL_INVALID_DATA;
1108 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_DECODE_PKT,reason));
1112 // switch to unsync - clear decode state
1113 m_output_elem.setType(OCSD_GEN_TRC_ELEM_NO_SYNC);
1114 resp = outputTraceElement(m_output_elem);
1116 m_curr_state = WAIT_SYNC;
1121 /* End of File trc_pkt_decode_etmv4i.cpp */