• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * \file       trc_pkt_decode_etmv4i.cpp
3  * \brief      OpenCSD : ETMv4 decoder
4  *
5  * \copyright  Copyright (c) 2015, ARM Limited. All Rights Reserved.
6  */
7 
8 /*
9  * Redistribution and use in source and binary forms, with or without modification,
10  * are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the copyright holder nor the names of its contributors
20  * may be used to endorse or promote products derived from this software without
21  * specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include <cstdlib>
36 
37 #include "opencsd/etmv4/trc_pkt_decode_etmv4i.h"
38 
39 #include "common/trc_gen_elem.h"
40 
41 
42 #define DCD_NAME "DCD_ETMV4"
43 
44 static const uint32_t ETMV4_SUPPORTED_DECODE_OP_FLAGS =
45     OCSD_OPFLG_PKTDEC_COMMON |  /* common op flags */
46     ETE_ETM4_OPFLG_MASK;        /* ete - etm4 op flags */
47 
TrcPktDecodeEtmV4I()48 TrcPktDecodeEtmV4I::TrcPktDecodeEtmV4I()
49     : TrcPktDecodeBase(DCD_NAME)
50 {
51     initDecoder();
52 }
53 
TrcPktDecodeEtmV4I(int instIDNum)54 TrcPktDecodeEtmV4I::TrcPktDecodeEtmV4I(int instIDNum)
55     : TrcPktDecodeBase(DCD_NAME,instIDNum)
56 {
57     initDecoder();
58 }
59 
~TrcPktDecodeEtmV4I()60 TrcPktDecodeEtmV4I::~TrcPktDecodeEtmV4I()
61 {
62 }
63 
64 /*********************** implementation packet decoding interface */
65 
processPacket()66 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processPacket()
67 {
68     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
69     ocsd_err_t err = OCSD_OK;
70     bool bPktDone = false;
71 
72     while(!bPktDone)
73     {
74         switch (m_curr_state)
75         {
76         case NO_SYNC:
77             // output the initial not synced packet to the sink
78             err = m_out_elem.resetElemStack();
79             if (!err)
80                 err = m_out_elem.addElemType(m_index_curr_pkt, OCSD_GEN_TRC_ELEM_NO_SYNC);
81             if (!err)
82             {
83                 outElem().setUnSyncEOTReason(m_unsync_eot_info);
84                 resp = m_out_elem.sendElements();
85                 m_curr_state = WAIT_SYNC;
86             }
87             else
88                 resp = OCSD_RESP_FATAL_SYS_ERR;
89 
90             // fall through to check if the current packet is the async we are waiting for.
91             break;
92 
93         case WAIT_SYNC:
94             if(m_curr_packet_in->getType() == ETM4_PKT_I_ASYNC)
95                 m_curr_state = WAIT_TINFO;
96             bPktDone = true;
97             break;
98 
99         case WAIT_TINFO:
100             m_need_ctxt = true;
101             m_need_addr = true;
102             if(m_curr_packet_in->getType() == ETM4_PKT_I_TRACE_INFO)
103             {
104                 doTraceInfoPacket();
105                 m_curr_state = DECODE_PKTS;
106                 m_return_stack.flush();
107             }
108             /* ETE spec allows early event packets. */
109             else if ((m_config->MajVersion() >= 0x5) &&
110                      (m_curr_packet_in->getType() == ETM4_PKT_I_EVENT))
111             {
112                 err = decodePacket();
113                 if (err)
114                     resp = OCSD_RESP_FATAL_INVALID_DATA;
115             }
116             bPktDone = true;
117             break;
118 
119         case DECODE_PKTS:
120             // this may change the state to RESOLVE_ELEM if required;
121             err = decodePacket();
122             if (err)
123             {
124                 // may want to continue through bad packets
125                 if ((err == OCSD_ERR_BAD_DECODE_PKT) || (err == OCSD_ERR_UNSUPP_DECODE_PKT))
126                 {
127                     if (getComponentOpMode() & OCSD_OPFLG_PKTDEC_HALT_BAD_PKTS)
128                         resp = OCSD_RESP_FATAL_INVALID_DATA;
129                     else if (getComponentOpMode() & OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS)
130                         resp = OCSD_RESP_ERR_CONT;
131                     else
132                         resp = OCSD_RESP_WARN_CONT;
133                 }
134                 else
135                     resp = OCSD_RESP_FATAL_INVALID_DATA;
136 
137                 bPktDone = true;
138             }
139             else if (m_curr_state != RESOLVE_ELEM)
140                 bPktDone = true;
141             break;
142 
143         case RESOLVE_ELEM:
144             // this will change the state to DECODE_PKTS once required elem resolved &
145             // needed generic packets output
146             resp = resolveElements();
147             if ((m_curr_state == DECODE_PKTS) || (!OCSD_DATA_RESP_IS_CONT(resp)))
148                 bPktDone = true;
149             break;
150         }
151     }
152     return resp;
153 }
154 
onEOT()155 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::onEOT()
156 {
157     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
158     ocsd_err_t err;
159     if ((err = commitElemOnEOT()) != OCSD_OK)
160     {
161         resp = OCSD_RESP_FATAL_INVALID_DATA;
162         LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, "Error flushing element stack at end of trace data."));
163     }
164     else
165         resp = m_out_elem.sendElements();
166     return resp;
167 }
168 
onReset()169 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::onReset()
170 {
171     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
172     m_unsync_eot_info = UNSYNC_RESET_DECODER;
173     resetDecoder();
174     return resp;
175 }
176 
onFlush()177 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::onFlush()
178 {
179     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
180 
181     if (m_curr_state == RESOLVE_ELEM)
182         resp = resolveElements();
183     else
184         resp = m_out_elem.sendElements();
185     return resp;
186 }
187 
onProtocolConfig()188 ocsd_err_t TrcPktDecodeEtmV4I::onProtocolConfig()
189 {
190     ocsd_err_t err = OCSD_OK;
191 
192     // set some static config elements
193     m_CSID = m_config->getTraceID();
194     m_max_spec_depth = m_config->MaxSpecDepth();
195 
196     // elements associated with data trace
197 #ifdef DATA_TRACE_SUPPORTED
198     m_p0_key_max = m_config->P0_Key_Max();
199     m_cond_key_max_incr = m_config->CondKeyMaxIncr();
200 #endif
201 
202     m_out_elem.initCSID(m_CSID);
203 
204     // set up static trace instruction decode elements
205     m_instr_info.dsb_dmb_waypoints = 0;
206     m_instr_info.wfi_wfe_branch = m_config->wfiwfeBranch() ? 1 : 0;
207     m_instr_info.pe_type.arch = m_config->archVersion();
208     m_instr_info.pe_type.profile = m_config->coreProfile();
209 
210     m_IASize64 = (m_config->iaSizeMax() == 64);
211 
212     if (m_config->enabledRetStack())
213     {
214         m_return_stack.set_active(true);
215 #ifdef TRC_RET_STACK_DEBUG
216         m_return_stack.set_dbg_logger(this);
217 #endif
218     }
219 
220     // check config compatible with current decoder support level.
221     // at present no data trace, no spec depth, no return stack, no QE
222     // Remove these checks as support is added.
223     if(m_config->enabledDataTrace())
224     {
225         err = OCSD_ERR_HW_CFG_UNSUPP;
226         LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : Data trace elements not supported"));
227     }
228     else if(m_config->enabledLSP0Trace())
229     {
230         err = OCSD_ERR_HW_CFG_UNSUPP;
231         LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : LSP0 elements not supported."));
232     }
233     else if(m_config->enabledCondITrace() != EtmV4Config::COND_TR_DIS)
234     {
235         err = OCSD_ERR_HW_CFG_UNSUPP;
236         LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : Trace on conditional non-branch elements not supported."));
237     }
238 
239     // set consistency check flags
240     m_direct_br_chk = (bool)(getComponentOpMode() & OCSD_OPFLG_N_UNCOND_DIR_BR_CHK);
241     m_strict_br_chk = (bool)(getComponentOpMode() & OCSD_OPFLG_STRICT_N_UNCOND_BR_CHK);
242     m_range_cont_chk = (bool)(getComponentOpMode() & OCSD_OPFLG_CHK_RANGE_CONTINUE);
243 
244     return err;
245 }
246 
247 /************* local decode methods */
initDecoder()248 void TrcPktDecodeEtmV4I::initDecoder()
249 {
250     // set the operational modes supported.
251     m_supported_op_flags = ETMV4_SUPPORTED_DECODE_OP_FLAGS;
252 
253     /* init elements that get set by config */
254     m_max_spec_depth = 0;
255     m_CSID = 0;
256     m_IASize64 = false;
257 
258     // set debug range limit - look for debugging env var
259     char* env_var;
260     long env_val;
261 
262     m_num_instr_range_limit = 0;
263     if ((env_var = getenv(OCSD_ENV_INSTR_RANGE_LIMIT)) != NULL)
264     {
265         env_val = strtol(env_var, NULL, 0);
266         /* if valid number set limit */
267         if (env_val > 0)
268             m_num_instr_range_limit = env_val;
269 
270     }
271 
272     // elements associated with data trace
273 #ifdef DATA_TRACE_SUPPORTED
274     m_p0_key_max = 0;
275     m_cond_key_max_incr = 0;
276 #endif
277 
278     // reset decoder state to unsynced
279     m_unsync_eot_info = UNSYNC_INIT_DECODER;
280     resetDecoder();
281 }
282 
resetDecoder()283 void TrcPktDecodeEtmV4I::resetDecoder()
284 {
285     m_curr_state = NO_SYNC;
286     m_timestamp = 0;
287     m_context_id = 0;
288     m_vmid_id = 0;
289     m_is_secure = true;
290     m_is_64bit = false;
291     m_cc_threshold = 0;
292     m_curr_spec_depth = 0;
293     m_need_ctxt = true;
294     m_need_addr = true;
295     m_elem_pending_addr = false;
296     m_prev_overflow = false;
297     m_P0_stack.delete_all();
298     m_out_elem.resetElemStack();
299     m_last_IS = 0;
300     clearElemRes();
301     m_ete_first_ts_marker = false;
302     nextRangeCheckClear();
303 
304     // elements associated with data trace
305 #ifdef DATA_TRACE_SUPPORTED
306     m_p0_key = 0;
307     m_cond_c_key = 0;
308     m_cond_r_key = 0;
309 #endif
310 }
311 
onFirstInitOK()312 void TrcPktDecodeEtmV4I::onFirstInitOK()
313 {
314     // once init, set the output element interface to the out elem list.
315     m_out_elem.initSendIf(this->getTraceElemOutAttachPt());
316 }
317 
318 // Changes a packet into stack of trace elements - these will be resolved and output later
decodePacket()319 ocsd_err_t TrcPktDecodeEtmV4I::decodePacket()
320 {
321     ocsd_err_t err = OCSD_OK;
322     bool bAllocErr = false;
323     bool is_addr = false;
324 
325     switch(m_curr_packet_in->getType())
326     {
327     case ETM4_PKT_I_ASYNC: // nothing to do with this packet.
328     case ETM4_PKT_I_IGNORE: // or this one.
329         break;
330 
331     case ETM4_PKT_I_TRACE_INFO:
332         // skip subsequent TInfo packets.
333         m_return_stack.flush();
334         break;
335 
336     case ETM4_PKT_I_TRACE_ON:
337         {
338             if (m_P0_stack.createParamElemNoParam(P0_TRC_ON, false, m_curr_packet_in->getType(), m_index_curr_pkt) == 0)
339                 bAllocErr = true;
340         }
341         break;
342 
343     case ETM4_PKT_I_ATOM_F1:
344     case ETM4_PKT_I_ATOM_F2:
345     case ETM4_PKT_I_ATOM_F3:
346     case ETM4_PKT_I_ATOM_F4:
347     case ETM4_PKT_I_ATOM_F5:
348     case ETM4_PKT_I_ATOM_F6:
349         {
350             if (m_P0_stack.createAtomElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getAtom()) == 0)
351                 bAllocErr = true;
352             else
353                 m_curr_spec_depth += m_curr_packet_in->getAtom().num;
354         }
355         break;
356 
357     case ETM4_PKT_I_CTXT:
358         {
359             if (m_P0_stack.createContextElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getContext(), m_last_IS) == 0)
360                 bAllocErr = true;
361         }
362         break;
363 
364     case ETM4_PKT_I_ADDR_MATCH:
365         {
366             etmv4_addr_val_t addr;
367 
368             addr.val = m_curr_packet_in->getAddrVal();
369             addr.isa = m_last_IS = m_curr_packet_in->getAddrIS();
370 
371             if (m_P0_stack.createAddrElem(m_curr_packet_in->getType(), m_index_curr_pkt, addr) == 0)
372                 bAllocErr = true;
373             is_addr = true;
374         }
375         break;
376 
377     case ETM4_PKT_I_ADDR_CTXT_L_64IS0:
378     case ETM4_PKT_I_ADDR_CTXT_L_64IS1:
379     case ETM4_PKT_I_ADDR_CTXT_L_32IS0:
380     case ETM4_PKT_I_ADDR_CTXT_L_32IS1:
381         {
382             m_last_IS = m_curr_packet_in->getAddrIS();
383             if (m_P0_stack.createContextElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getContext(), m_last_IS) == 0)
384                 bAllocErr = true;
385         }
386     case ETM4_PKT_I_ADDR_L_32IS0:
387     case ETM4_PKT_I_ADDR_L_32IS1:
388     case ETM4_PKT_I_ADDR_L_64IS0:
389     case ETM4_PKT_I_ADDR_L_64IS1:
390     case ETM4_PKT_I_ADDR_S_IS0:
391     case ETM4_PKT_I_ADDR_S_IS1:
392         {
393             etmv4_addr_val_t addr;
394 
395             addr.val = m_curr_packet_in->getAddrVal();
396             addr.isa = m_last_IS = m_curr_packet_in->getAddrIS();
397 
398             if (m_P0_stack.createAddrElem(m_curr_packet_in->getType(), m_index_curr_pkt, addr) == 0)
399                 bAllocErr = true;
400             is_addr = true;  // may be waiting for target address from indirect branch
401         }
402         break;
403 
404     case ETE_PKT_I_SRC_ADDR_MATCH:
405     case ETE_PKT_I_SRC_ADDR_S_IS0:
406     case ETE_PKT_I_SRC_ADDR_S_IS1:
407     case ETE_PKT_I_SRC_ADDR_L_32IS0:
408     case ETE_PKT_I_SRC_ADDR_L_32IS1:
409     case ETE_PKT_I_SRC_ADDR_L_64IS0:
410     case ETE_PKT_I_SRC_ADDR_L_64IS1:
411         {
412             etmv4_addr_val_t addr;
413 
414             addr.val = m_curr_packet_in->getAddrVal();
415             addr.isa = m_curr_packet_in->getAddrIS();
416             if (m_P0_stack.createSrcAddrElem(m_curr_packet_in->getType(), m_index_curr_pkt, addr) == 0)
417                 bAllocErr = true;
418             m_curr_spec_depth++;
419         }
420         break;
421 
422     // Exceptions
423     case ETM4_PKT_I_EXCEPT:
424          {
425             if (m_P0_stack.createExceptElem(m_curr_packet_in->getType(), m_index_curr_pkt,
426                                             (m_curr_packet_in->exception_info.addr_interp == 0x2),
427                                             m_curr_packet_in->exception_info.exceptionType) == 0)
428                 bAllocErr = true;
429             else
430                 m_elem_pending_addr = true;  // wait for following packets before marking for commit.
431         }
432         break;
433 
434     case ETM4_PKT_I_EXCEPT_RTN:
435         {
436             // P0 element if V7M profile.
437             bool bV7MProfile = (m_config->archVersion() == ARCH_V7) && (m_config->coreProfile() == profile_CortexM);
438             if (m_P0_stack.createParamElemNoParam(P0_EXCEP_RET, bV7MProfile, m_curr_packet_in->getType(), m_index_curr_pkt) == 0)
439                 bAllocErr = true;
440             else if (bV7MProfile)
441                 m_curr_spec_depth++;
442         }
443         break;
444 
445     case ETM4_PKT_I_FUNC_RET:
446         {
447             // P0 element iff V8M profile, otherwise ignore
448             if (OCSD_IS_V8_ARCH(m_config->archVersion()) && (m_config->coreProfile() == profile_CortexM))
449             {
450                 if (m_P0_stack.createParamElemNoParam(P0_FUNC_RET, true, m_curr_packet_in->getType(), m_index_curr_pkt) == 0)
451                     bAllocErr = true;
452                 else
453                     m_curr_spec_depth++;
454             }
455         }
456         break;
457 
458     // event trace
459     case ETM4_PKT_I_EVENT:
460         {
461             std::vector<uint32_t> params = { 0 };
462             params[0] = (uint32_t)m_curr_packet_in->event_val;
463             if (m_P0_stack.createParamElem(P0_EVENT, false, m_curr_packet_in->getType(), m_index_curr_pkt, params) == 0)
464                 bAllocErr = true;
465 
466         }
467         break;
468 
469     /* cycle count packets */
470     case ETM4_PKT_I_CCNT_F1:
471     case ETM4_PKT_I_CCNT_F2:
472     case ETM4_PKT_I_CCNT_F3:
473         {
474             std::vector<uint32_t> params = { 0 };
475             params[0] = m_curr_packet_in->getCC();
476             if (m_P0_stack.createParamElem(P0_CC, false, m_curr_packet_in->getType(), m_index_curr_pkt, params) == 0)
477                 bAllocErr = true;
478 
479         }
480         break;
481 
482     // timestamp
483     case ETM4_PKT_I_TIMESTAMP:
484         {
485             bool bTSwithCC = m_config->enabledCCI();
486             uint64_t ts = m_curr_packet_in->getTS();
487             std::vector<uint32_t> params = { 0, 0, 0 };
488             params[0] = (uint32_t)(ts & 0xFFFFFFFF);
489             params[1] = (uint32_t)((ts >> 32) & 0xFFFFFFFF);
490             if (bTSwithCC)
491                 params[2] = m_curr_packet_in->getCC();
492             if (m_P0_stack.createParamElem(bTSwithCC ? P0_TS_CC : P0_TS, false, m_curr_packet_in->getType(), m_index_curr_pkt, params) == 0)
493                 bAllocErr = true;
494 
495         }
496         break;
497 
498     case ETE_PKT_I_TS_MARKER:
499         {
500             trace_marker_payload_t marker;
501             marker.type = ELEM_MARKER_TS;
502             marker.value = 0;
503             if (m_P0_stack.createMarkerElem(m_curr_packet_in->getType(), m_index_curr_pkt, marker) == 0)
504                 bAllocErr = true;
505         }
506         break;
507 
508     case ETM4_PKT_I_BAD_SEQUENCE:
509         err = handleBadPacket("Bad byte sequence in packet.", m_index_curr_pkt);
510         break;
511 
512     case ETM4_PKT_I_BAD_TRACEMODE:
513         err = handleBadPacket("Invalid packet type for trace mode.", m_index_curr_pkt);
514         break;
515 
516     case ETM4_PKT_I_RESERVED:
517         err = handleBadPacket("Reserved packet header", m_index_curr_pkt);
518         break;
519 
520     // speculation
521     case ETM4_PKT_I_MISPREDICT:
522     case ETM4_PKT_I_CANCEL_F1_MISPRED:
523     case ETM4_PKT_I_CANCEL_F2:
524     case ETM4_PKT_I_CANCEL_F3:
525         m_elem_res.mispredict = true;
526         if (m_curr_packet_in->getNumAtoms())
527         {
528             if (m_P0_stack.createAtomElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getAtom()) == 0)
529                 bAllocErr = true;
530             else
531                 m_curr_spec_depth += m_curr_packet_in->getNumAtoms();
532         }
533 
534     case ETM4_PKT_I_CANCEL_F1:
535         m_elem_res.P0_cancel = m_curr_packet_in->getCancelElem();
536         break;
537 
538     case ETM4_PKT_I_COMMIT:
539         m_elem_res.P0_commit = m_curr_packet_in->getCommitElem();
540         break;
541 
542     case ETM4_PKT_I_OVERFLOW:
543         m_prev_overflow = true;
544     case ETM4_PKT_I_DISCARD:
545         m_curr_spec_depth = 0;
546         m_elem_res.discard = true;
547         break;
548 
549         /* Q packets */
550     case ETM4_PKT_I_Q:
551         {
552             TrcStackQElem *pQElem = m_P0_stack.createQElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->Q_pkt.q_count);
553             if (pQElem)
554             {
555                 if (m_curr_packet_in->Q_pkt.addr_present)
556                 {
557                     etmv4_addr_val_t addr;
558 
559                     addr.val = m_curr_packet_in->getAddrVal();
560                     addr.isa = m_curr_packet_in->getAddrIS();
561                     pQElem->setAddr(addr);
562                     m_curr_spec_depth++;
563                 }
564                 else
565                     m_elem_pending_addr = true;
566             }
567             else
568                 bAllocErr = true;
569         }
570         break;
571 
572         /* transactional memory packets */
573     case ETE_PKT_I_TRANS_ST:
574         {
575             if (m_P0_stack.createParamElemNoParam(P0_TRANS_START, m_config->commTransP0(), m_curr_packet_in->getType(), m_index_curr_pkt) == 0)
576                 bAllocErr = true;
577             if (m_config->commTransP0())
578                 m_curr_spec_depth++;
579         }
580         break;
581 
582     case ETE_PKT_I_TRANS_COMMIT:
583         {
584             if (m_P0_stack.createParamElemNoParam(P0_TRANS_COMMIT, false, m_curr_packet_in->getType(), m_index_curr_pkt) == 0)
585                 bAllocErr = true;
586         }
587         break;
588 
589     case ETE_PKT_I_TRANS_FAIL:
590         {
591             if (m_P0_stack.createParamElemNoParam(P0_TRANS_FAIL, false, m_curr_packet_in->getType(), m_index_curr_pkt) == 0)
592                 bAllocErr = true;
593         }
594         break;
595 
596         /* PE Instrumentation packet */
597     case ETE_PKT_I_ITE:
598         {
599             trace_sw_ite_t ite_pkt;
600 
601             ite_pkt.el = m_curr_packet_in->getITE_EL();
602             ite_pkt.value = m_curr_packet_in->getITE_value();
603             if (m_P0_stack.createITEElem(m_curr_packet_in->getType(), m_index_curr_pkt, ite_pkt) == 0)
604                 bAllocErr = true;
605         }
606         break;
607 
608     /*** presently unsupported packets ***/
609         /* conditional instruction tracing */
610     case ETM4_PKT_I_COND_FLUSH:
611     case ETM4_PKT_I_COND_I_F1:
612     case ETM4_PKT_I_COND_I_F2:
613     case ETM4_PKT_I_COND_I_F3:
614     case ETM4_PKT_I_COND_RES_F1:
615     case ETM4_PKT_I_COND_RES_F2:
616     case ETM4_PKT_I_COND_RES_F3:
617     case ETM4_PKT_I_COND_RES_F4:
618     // data synchronisation markers
619     case ETM4_PKT_I_NUM_DS_MKR:
620     case ETM4_PKT_I_UNNUM_DS_MKR:
621         // all currently unsupported
622         err = handlePacketSeqErr(OCSD_ERR_UNSUPP_DECODE_PKT, m_index_curr_pkt, "Data trace related, unsupported packet type.");
623         break;
624 
625     default:
626         // any other packet - bad packet error
627         err = handleBadPacket("Unknown packet type.", m_index_curr_pkt);
628         break;
629     }
630 
631     // we need to wait for following address after certain packets
632     // - work out if we have seen enough here...
633     if (is_addr && m_elem_pending_addr)
634     {
635         m_curr_spec_depth++;  // increase spec depth for element waiting on address.
636         m_elem_pending_addr = false;  // can't be waiting on both
637     }
638 
639     if(bAllocErr)
640     {
641         err = OCSD_ERR_MEM;
642         LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_MEM,"Memory allocation error."));
643     }
644     else if(m_curr_spec_depth > m_max_spec_depth)
645     {
646         // auto commit anything above max spec depth
647         // (this will auto commit anything if spec depth not supported!)
648         m_elem_res.P0_commit = m_curr_spec_depth - m_max_spec_depth;
649     }
650 
651     if (!err && isElemForRes())
652         m_curr_state = RESOLVE_ELEM;
653     return err;
654 }
655 
doTraceInfoPacket()656 void TrcPktDecodeEtmV4I::doTraceInfoPacket()
657 {
658     m_trace_info = m_curr_packet_in->getTraceInfo();
659     m_cc_threshold = m_curr_packet_in->getCCThreshold();
660     m_curr_spec_depth = m_curr_packet_in->getCurrSpecDepth();
661     /* put a trans marker in stack if started in trans state */
662     if (m_trace_info.bits.in_trans_state)
663         m_P0_stack.createParamElemNoParam(P0_TRANS_TRACE_INIT, false, m_curr_packet_in->getType(), m_index_curr_pkt);
664 
665     // elements associated with data trace
666 #ifdef DATA_TRACE_SUPPORTED
667     m_p0_key = m_curr_packet_in->getP0Key();
668 #endif
669 }
670 
671 /* Element resolution
672  * Commit or cancel elements as required
673  * Send any buffered output packets.
674  */
resolveElements()675 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::resolveElements()
676 {
677     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
678     bool Complete = false;
679 
680     while (!Complete)
681     {
682         if (m_out_elem.numElemToSend())
683             resp = m_out_elem.sendElements();
684         else if (isElemForRes())
685         {
686             ocsd_err_t err = OCSD_OK;
687             if (m_elem_res.P0_commit)
688                 err = commitElements();
689 
690             // allow for early flush on context element
691             if (!m_elem_res.P0_commit) {
692 
693                 if (!err && m_elem_res.P0_cancel)
694                     err = cancelElements();
695 
696                 if (!err && m_elem_res.mispredict)
697                     err = mispredictAtom();
698 
699                 if (!err && m_elem_res.discard)
700                     err = discardElements();
701             }
702 
703             if (err != OCSD_OK) {
704                 // has the error reset the decoder?
705                 if (m_curr_state == NO_SYNC)
706                     resp = OCSD_RESP_ERR_CONT;
707                 else
708                     resp = OCSD_RESP_FATAL_INVALID_DATA;
709             }
710         }
711 
712         // break out on error or wait request.
713         if (!OCSD_DATA_RESP_IS_CONT(resp))
714             break;
715 
716         // completion is nothing to send and nothing to commit
717         Complete = !m_out_elem.numElemToSend() && !isElemForRes();
718 
719         // done all elements - need more packets.
720         if (Complete) {
721             // if we are still in resolve, the goto decode.
722             if (m_curr_state == RESOLVE_ELEM)
723                 m_curr_state = DECODE_PKTS;
724         }
725     }
726     return resp;
727 }
728 
729 /*
730  * Walks through the element stack, processing from oldest element to the newest,
731    according to the number of P0 elements that need committing.
732    Build a stack of output elements in the process.
733  */
commitElements()734 ocsd_err_t TrcPktDecodeEtmV4I::commitElements()
735 {
736     ocsd_err_t err = OCSD_OK;
737     bool bPopElem = true;       // do we remove the element from the stack (multi atom elements may need to stay!)
738     int num_commit_req = m_elem_res.P0_commit;
739     ocsd_trc_index_t err_idx = 0;
740     TrcStackElem *pElem = 0;    // stacked element pointer
741     bool contextFlush = false;
742 
743     err = m_out_elem.resetElemStack();
744 
745     while(m_elem_res.P0_commit && !err && !contextFlush)
746     {
747         if (m_P0_stack.size() > 0)
748         {
749             pElem = m_P0_stack.back();  // get oldest element
750             err_idx = pElem->getRootIndex(); // save index in case of error.
751 
752             switch (pElem->getP0Type())
753             {
754                 // indicates a trace restart - beginning of trace or discontinuiuty
755             case P0_TRC_ON:
756                 nextRangeCheckClear();
757                 err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_TRACE_ON);
758                 if (!err)
759                 {
760                     m_out_elem.getCurrElem().trace_on_reason = m_prev_overflow ? TRACE_ON_OVERFLOW : TRACE_ON_NORMAL;
761                     m_prev_overflow = false;
762                     m_return_stack.flush();
763                 }
764                 break;
765 
766             case P0_ADDR:
767                 {
768                 TrcStackElemAddr *pAddrElem = dynamic_cast<TrcStackElemAddr *>(pElem);
769                 m_return_stack.clear_pop_pending(); // address removes the need to pop the indirect address target from the stack
770                 if (pAddrElem)
771                 {
772                     SetInstrInfoInAddrISA(pAddrElem->getAddr().val, pAddrElem->getAddr().isa);
773                     m_need_addr = false;
774                 }
775                 }
776                 break;
777 
778             case P0_CTXT:
779                 {
780                 TrcStackElemCtxt *pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem);
781                 if (pCtxtElem)
782                 {
783                     etmv4_context_t ctxt = pCtxtElem->getContext();
784                     // check this is an updated context
785                     if(ctxt.updated)
786                     {
787                         err = m_out_elem.addElem(pElem->getRootIndex());
788                         if (!err) {
789                             updateContext(pCtxtElem, outElem());
790 
791                             // updated context - need to force this to be output to the client so correct memory
792                             // context can be used.
793                             contextFlush = true;
794 
795                             // invalidate memory accessor cacheing - force next memory access out to client to
796                             // ensure that the correct memory context is in play when decoding subsequent atoms.
797                             invalidateMemAccCache();
798                         }
799                     }
800                 }
801                 }
802                 break;
803 
804             case P0_EVENT:
805             case P0_TS:
806             case P0_CC:
807             case P0_TS_CC:
808                 err = processTS_CC_EventElem(pElem);
809                 break;
810 
811             case P0_MARKER:
812                 err = processMarkerElem(pElem);
813                 break;
814 
815             case P0_ATOM:
816                 {
817                 TrcStackElemAtom *pAtomElem = dynamic_cast<TrcStackElemAtom *>(pElem);
818 
819                 if (pAtomElem)
820                 {
821                     while(!pAtomElem->isEmpty() && m_elem_res.P0_commit && !err)
822                     {
823                         ocsd_atm_val atom = pAtomElem->commitOldest();
824 
825                         // check if prev atom was indirect branch - may need address from return stack
826                         if ((err = returnStackPop()) != OCSD_OK)
827                             break;
828 
829                         // if address and context do instruction trace follower.
830                         // otherwise skip atom and reduce committed elements
831                         // allow for insufficient program image.
832                         if (!m_need_ctxt && !m_need_addr)
833                         {
834                             if ((err = processAtom(atom)) != OCSD_OK)
835                                 break;
836                         }
837                         if (m_elem_res.P0_commit)
838                             m_elem_res.P0_commit--; // mark committed
839                     }
840                     if (!pAtomElem->isEmpty())
841                         bPopElem = false;   // don't remove if still atoms to process.
842                 }
843                 }
844                 break;
845 
846             case P0_EXCEP:
847                 // check if prev atom left us an indirect address target on the return stack
848                 if ((err = returnStackPop()) != OCSD_OK)
849                     break;
850 
851                 nextRangeCheckClear();
852                 err = processException();  // output trace + exception elements.
853                 m_elem_res.P0_commit--;
854                 break;
855 
856             case P0_EXCEP_RET:
857                 nextRangeCheckClear();
858                 err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_EXCEPTION_RET);
859                 if (!err)
860                 {
861                     if (pElem->isP0()) // are we on a core that counts ERET as P0?
862                         m_elem_res.P0_commit--;
863                 }
864                 break;
865 
866             case P0_FUNC_RET:
867                 // func ret is V8M - data trace only - hint that data has been popped off the stack.
868                 // at this point nothing to do till the decoder starts handling data trace.
869                 if (pElem->isP0())
870                     m_elem_res.P0_commit--;
871                 break;
872 
873             case P0_SRC_ADDR:
874                 nextRangeCheckClear();
875                 err = processSourceAddress();
876                 m_elem_res.P0_commit--;
877                 break;
878 
879             case P0_Q:
880                 nextRangeCheckClear();
881                 err = processQElement();
882                 m_elem_res.P0_commit--;
883 				break;
884 
885             case P0_TRANS_START:
886                 if (m_config->commTransP0())
887                     m_elem_res.P0_commit--;
888             case P0_TRANS_COMMIT:
889             case P0_TRANS_FAIL:
890             case P0_TRANS_TRACE_INIT:
891                 nextRangeCheckClear();
892                 err = processTransElem(pElem);
893                 break;
894 
895             case P0_ITE:
896                 err = processITEElem(pElem);
897                 break;
898             }
899 
900             if(bPopElem)
901                 m_P0_stack.delete_back();  // remove element from stack;
902         }
903         else
904         {
905             // too few elements for commit operation - decode error.
906             err = handlePacketSeqErr(OCSD_ERR_COMMIT_PKT_OVERRUN, err_idx, "Not enough elements to commit");
907         }
908     }
909 
910     // reduce the spec depth by number of comitted elements
911     m_curr_spec_depth -= (num_commit_req-m_elem_res.P0_commit);
912     return err;
913 }
914 
returnStackPop()915 ocsd_err_t TrcPktDecodeEtmV4I::returnStackPop()
916 {
917     ocsd_err_t err = OCSD_OK;
918     ocsd_isa nextISA;
919 
920     if (m_return_stack.pop_pending())
921     {
922         ocsd_vaddr_t popAddr = m_return_stack.pop(nextISA);
923         if (m_return_stack.overflow())
924         {
925             err = OCSD_ERR_RET_STACK_OVERFLOW;
926             err = handlePacketSeqErr(err, OCSD_BAD_TRC_INDEX, "Trace Return Stack Overflow.");
927         }
928         else
929         {
930             m_instr_info.instr_addr = popAddr;
931             m_instr_info.isa = nextISA;
932             m_need_addr = false;
933         }
934     }
935     return err;
936 }
937 
commitElemOnEOT()938 ocsd_err_t TrcPktDecodeEtmV4I::commitElemOnEOT()
939 {
940     ocsd_err_t err = OCSD_OK;
941     TrcStackElem *pElem = 0;
942 
943     // nothing outstanding - reset the stack before we add more
944     if (!m_out_elem.numElemToSend())
945         m_out_elem.resetElemStack();
946 
947     while((m_P0_stack.size() > 0) && !err)
948     {
949         // scan for outstanding events, TS and CC, that appear before any outstanding
950         // uncommited P0 element.
951         pElem = m_P0_stack.back();
952 
953             switch(pElem->getP0Type())
954             {
955                 // clear stack and stop
956             case P0_UNKNOWN:
957             case P0_ATOM:
958             case P0_TRC_ON:
959             case P0_EXCEP:
960             case P0_EXCEP_RET:
961             case P0_OVERFLOW:
962             case P0_Q:
963                 m_P0_stack.delete_all();
964                 break;
965 
966             //skip
967         case P0_ADDR:
968         case P0_CTXT:
969             break;
970 
971             // trans
972             // P0 trans - clear and stop, otherwise skip
973         case P0_TRANS_START:
974             if (m_config->commTransP0())
975                 m_P0_stack.delete_all();
976             break;
977 
978             // non-speculative trans fail / commit - could appear at EoT after valid trace
979             // but without a subsequent P0 that would force output.
980         case P0_TRANS_FAIL:
981         case P0_TRANS_COMMIT:
982             if (m_max_spec_depth == 0 || m_curr_spec_depth == 0)
983                 err = processTransElem(pElem);
984             break;
985 
986             // others - skip non P0
987         case P0_TRANS_TRACE_INIT:
988             break;
989 
990             // output
991         case P0_EVENT:
992         case P0_TS:
993         case P0_CC:
994         case P0_TS_CC:
995             err = processTS_CC_EventElem(pElem);
996             break;
997 
998         case P0_MARKER:
999             err = processMarkerElem(pElem);
1000             break;
1001 
1002         case P0_ITE:
1003             err = processITEElem(pElem);
1004             break;
1005         }
1006         m_P0_stack.delete_back();
1007     }
1008 
1009     if(!err)
1010     {
1011         err = m_out_elem.addElemType(m_index_curr_pkt, OCSD_GEN_TRC_ELEM_EO_TRACE);
1012         outElem().setUnSyncEOTReason(m_prev_overflow ? UNSYNC_OVERFLOW : UNSYNC_EOT);
1013     }
1014     return err;
1015 }
1016 
1017 // cancel elements. These not output
cancelElements()1018 ocsd_err_t TrcPktDecodeEtmV4I::cancelElements()
1019 {
1020     ocsd_err_t err = OCSD_OK;
1021     bool P0StackDone = false;  // checked all P0 elements on the stack
1022     TrcStackElem *pElem = 0;   // stacked element pointer
1023     EtmV4P0Stack temp;
1024     int num_cancel_req = m_elem_res.P0_cancel;
1025 
1026     while (m_elem_res.P0_cancel)
1027     {
1028         //search the stack for the newest elements
1029         if (!P0StackDone)
1030         {
1031             if (m_P0_stack.size() == 0)
1032                 P0StackDone = true;
1033             else
1034             {
1035                 // get the newest element
1036                 pElem = m_P0_stack.front();
1037                 if (pElem->isP0()) {
1038                     if (pElem->getP0Type() == P0_ATOM)
1039                     {
1040                         TrcStackElemAtom *pAtomElem = (TrcStackElemAtom *)pElem;
1041                         // atom - cancel N atoms
1042                         m_elem_res.P0_cancel -= pAtomElem->cancelNewest(m_elem_res.P0_cancel);
1043                         if (pAtomElem->isEmpty())
1044                             m_P0_stack.delete_front();  // remove the element
1045                     }
1046                     else
1047                     {
1048                         m_elem_res.P0_cancel--;
1049                         m_P0_stack.delete_front();  // remove the element
1050                     }
1051                 } else {
1052                 // not P0, make a keep / remove decision
1053                     switch (pElem->getP0Type())
1054                     {
1055                     // keep these
1056                     case P0_EVENT:
1057                     case P0_TS:
1058                     case P0_CC:
1059                     case P0_TS_CC:
1060                     case P0_MARKER:
1061                     case P0_ITE:
1062                         m_P0_stack.pop_front(false);
1063                         temp.push_back(pElem);
1064                         break;
1065 
1066                     default:
1067                         m_P0_stack.delete_front();
1068                         break;
1069                     }
1070                 }
1071                 if (m_P0_stack.size() == 0)
1072                     P0StackDone = true;
1073             }
1074         }
1075         // may have some unseen elements
1076         else if (m_unseen_spec_elem)
1077         {
1078             m_unseen_spec_elem--;
1079             m_elem_res.P0_cancel--;
1080         }
1081         // otherwise we have some sort of overrun
1082         else
1083         {
1084             // too few elements for commit operation - decode error.
1085             err = OCSD_ERR_COMMIT_PKT_OVERRUN;
1086             err = handlePacketSeqErr(err, m_index_curr_pkt, "Not enough elements to cancel");
1087             m_elem_res.P0_cancel = 0;
1088             break;
1089         }
1090     }
1091 
1092     /* restore any saved elements that are unaffected by cancel. */
1093     if (temp.size())
1094     {
1095         while (temp.size())
1096         {
1097             pElem = temp.back();
1098             m_P0_stack.push_front(pElem);
1099             temp.pop_back(false);
1100         }
1101     }
1102 
1103     m_curr_spec_depth -= num_cancel_req - m_elem_res.P0_cancel;
1104     return err;
1105 }
1106 
1107 // mispredict an atom
mispredictAtom()1108 ocsd_err_t TrcPktDecodeEtmV4I::mispredictAtom()
1109 {
1110     ocsd_err_t err = OCSD_OK;
1111     bool bFoundAtom = false, bDone = false;
1112     TrcStackElem *pElem = 0;
1113 
1114     m_P0_stack.from_front_init();   // init iterator at front.
1115     while (!bDone)
1116     {
1117         pElem = m_P0_stack.from_front_next();
1118         if (pElem)
1119         {
1120             if (pElem->getP0Type() == P0_ATOM)
1121             {
1122                 TrcStackElemAtom *pAtomElem = dynamic_cast<TrcStackElemAtom *>(pElem);
1123                 if (pAtomElem)
1124                 {
1125                     pAtomElem->mispredictNewest();
1126                     bFoundAtom = true;
1127                 }
1128                 bDone = true;
1129             }
1130             else if (pElem->getP0Type() == P0_ADDR)
1131             {
1132                 // need to disregard any addresses that appear between mispredict and the atom in question
1133                 m_P0_stack.erase_curr_from_front();
1134             }
1135         }
1136         else
1137             bDone = true;
1138     }
1139 
1140     // if missed atom then either overrun error or mispredict on unseen element
1141     if (!bFoundAtom && !m_unseen_spec_elem)
1142     {
1143         err = OCSD_ERR_COMMIT_PKT_OVERRUN;
1144         err = handlePacketSeqErr(err, m_index_curr_pkt, "Not found mispredict atom");
1145         //LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, m_index_curr_pkt, m_CSID, "Not found mispredict atom"));
1146     }
1147     m_elem_res.mispredict = false;
1148     return err;
1149 }
1150 
1151 // discard elements and flush
discardElements()1152 ocsd_err_t TrcPktDecodeEtmV4I::discardElements()
1153 {
1154     ocsd_err_t err = OCSD_OK;
1155     TrcStackElem *pElem = 0;   // stacked element pointer
1156 
1157     // dump P0, elemnts - output remaining CC / TS
1158     while ((m_P0_stack.size() > 0) && !err)
1159     {
1160         pElem = m_P0_stack.back();
1161         if (pElem->getP0Type() == P0_MARKER)
1162             err = processMarkerElem(pElem);
1163         else if (pElem->getP0Type() == P0_MARKER)
1164             err = processITEElem(pElem);
1165         else
1166             err = processTS_CC_EventElem(pElem);
1167         m_P0_stack.delete_back();
1168     }
1169 
1170     // clear all speculation info
1171     clearElemRes();
1172     m_curr_spec_depth = 0;
1173 
1174     // set decode state
1175     m_curr_state = NO_SYNC;
1176     m_unsync_eot_info = m_prev_overflow ? UNSYNC_OVERFLOW : UNSYNC_DISCARD;
1177 
1178     // unsync so need context & address.
1179     m_need_ctxt = true;
1180     m_need_addr = true;
1181     m_elem_pending_addr = false;
1182     return err;
1183 }
1184 
processTS_CC_EventElem(TrcStackElem * pElem)1185 ocsd_err_t TrcPktDecodeEtmV4I::processTS_CC_EventElem(TrcStackElem *pElem)
1186 {
1187     ocsd_err_t err = OCSD_OK;
1188     // ignore ts for ETE if not seen first TS marker on systems that use this.
1189     bool bPermitTS = !m_config->eteHasTSMarker() || m_ete_first_ts_marker;
1190 
1191     switch (pElem->getP0Type())
1192     {
1193         case P0_EVENT:
1194         {
1195             TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
1196             if (pParamElem)
1197                 err = addElemEvent(pParamElem);
1198         }
1199         break;
1200 
1201         case P0_TS:
1202         {
1203             TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
1204             if (pParamElem && bPermitTS)
1205                 err = addElemTS(pParamElem, false);
1206         }
1207         break;
1208 
1209         case P0_CC:
1210         {
1211             TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
1212             if (pParamElem)
1213                 err = addElemCC(pParamElem);
1214         }
1215         break;
1216 
1217         case P0_TS_CC:
1218         {
1219             TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
1220             if (pParamElem && bPermitTS)
1221                 err = addElemTS(pParamElem, true);
1222         }
1223         break;
1224     }
1225     return err;
1226 
1227 }
1228 
processMarkerElem(TrcStackElem * pElem)1229 ocsd_err_t TrcPktDecodeEtmV4I::processMarkerElem(TrcStackElem *pElem)
1230 {
1231     ocsd_err_t err = OCSD_OK;
1232     TrcStackElemMarker *pMarkerElem = dynamic_cast<TrcStackElemMarker *>(pElem);
1233 
1234     if (m_config->eteHasTSMarker() && (pMarkerElem->getMarker().type == ELEM_MARKER_TS))
1235         m_ete_first_ts_marker = true;
1236 
1237     if (!err)
1238     {
1239         err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_SYNC_MARKER);
1240         if (!err)
1241             m_out_elem.getCurrElem().setSyncMarker(pMarkerElem->getMarker());
1242     }
1243     return err;
1244 }
1245 
processTransElem(TrcStackElem * pElem)1246 ocsd_err_t TrcPktDecodeEtmV4I::processTransElem(TrcStackElem *pElem)
1247 {
1248     ocsd_err_t err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_MEMTRANS);
1249     if (!err)
1250     {
1251         outElem().setTransactionType((trace_memtrans_t)((int)OCSD_MEM_TRANS_FAIL -
1252             ((int)P0_TRANS_FAIL - (int)pElem->getP0Type())));
1253     }
1254     return err;
1255 }
1256 
processITEElem(TrcStackElem * pElem)1257 ocsd_err_t TrcPktDecodeEtmV4I::processITEElem(TrcStackElem *pElem)
1258 {
1259     ocsd_err_t err = OCSD_OK;
1260     TrcStackElemITE *pITEElem = dynamic_cast<TrcStackElemITE *>(pElem);
1261 
1262     err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_INSTRUMENTATION);
1263     if (!err) {
1264         outElem().setITEInfo(pITEElem->getITE());
1265     }
1266     return err;
1267 }
1268 
addElemCC(TrcStackElemParam * pParamElem)1269 ocsd_err_t TrcPktDecodeEtmV4I::addElemCC(TrcStackElemParam *pParamElem)
1270 {
1271     ocsd_err_t err = OCSD_OK;
1272 
1273     err = m_out_elem.addElemType(pParamElem->getRootIndex(), OCSD_GEN_TRC_ELEM_CYCLE_COUNT);
1274     if (!err)
1275         outElem().setCycleCount(pParamElem->getParam(0));
1276     return err;
1277 }
1278 
addElemTS(TrcStackElemParam * pParamElem,bool withCC)1279 ocsd_err_t TrcPktDecodeEtmV4I::addElemTS(TrcStackElemParam *pParamElem, bool withCC)
1280 {
1281     ocsd_err_t err = OCSD_OK;
1282 
1283     err = m_out_elem.addElemType(pParamElem->getRootIndex(), OCSD_GEN_TRC_ELEM_TIMESTAMP);
1284     if (!err)
1285     {
1286         outElem().timestamp = (uint64_t)(pParamElem->getParam(0)) | (((uint64_t)pParamElem->getParam(1)) << 32);
1287         if (withCC)
1288             outElem().setCycleCount(pParamElem->getParam(2));
1289     }
1290     return err;
1291 }
1292 
addElemEvent(TrcStackElemParam * pParamElem)1293 ocsd_err_t TrcPktDecodeEtmV4I::addElemEvent(TrcStackElemParam *pParamElem)
1294 {
1295     ocsd_err_t err = OCSD_OK;
1296 
1297     err = m_out_elem.addElemType(pParamElem->getRootIndex(), OCSD_GEN_TRC_ELEM_EVENT);
1298     if (!err)
1299     {
1300         outElem().trace_event.ev_type = EVENT_NUMBERED;
1301         outElem().trace_event.ev_number = pParamElem->getParam(0);
1302     }
1303     return err;
1304 }
1305 
setElemTraceRange(OcsdTraceElement & elemIn,const instr_range_t & addr_range,const bool executed,ocsd_trc_index_t index)1306 void TrcPktDecodeEtmV4I::setElemTraceRange(OcsdTraceElement &elemIn, const instr_range_t &addr_range,
1307     const bool executed, ocsd_trc_index_t index)
1308 {
1309     setElemTraceRangeInstr(elemIn, addr_range, executed, index, m_instr_info);
1310 }
1311 
setElemTraceRangeInstr(OcsdTraceElement & elemIn,const instr_range_t & addr_range,const bool executed,ocsd_trc_index_t index,ocsd_instr_info & instr)1312 void TrcPktDecodeEtmV4I::setElemTraceRangeInstr(OcsdTraceElement &elemIn, const instr_range_t &addr_range,
1313     const bool executed, ocsd_trc_index_t index, ocsd_instr_info &instr)
1314 {
1315     elemIn.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE);
1316     elemIn.setLastInstrInfo(executed, instr.type, instr.sub_type, instr.instr_size);
1317     elemIn.setISA(instr.isa);
1318     elemIn.setLastInstrCond(instr.is_conditional);
1319     elemIn.setAddrRange(addr_range.st_addr, addr_range.en_addr, addr_range.num_instr);
1320     if (executed)
1321         instr.isa = instr.next_isa;
1322 }
1323 
processAtom(const ocsd_atm_val atom)1324 ocsd_err_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom)
1325 {
1326     ocsd_err_t err;
1327     TrcStackElem *pElem = m_P0_stack.back();  // get the atom element
1328     WP_res_t WPRes;
1329     instr_range_t addr_range;
1330     bool ETE_ERET = false;
1331 
1332     // new element for this processed atom
1333     if ((err = m_out_elem.addElem(pElem->getRootIndex())) != OCSD_OK)
1334         return err;
1335 
1336     err = traceInstrToWP(addr_range, WPRes);
1337     if(err != OCSD_OK)
1338     {
1339         if(err == OCSD_ERR_UNSUPPORTED_ISA)
1340         {
1341              m_need_addr = true;
1342              m_need_ctxt = true;
1343              LogError(ocsdError(OCSD_ERR_SEV_WARN,err,pElem->getRootIndex(),m_CSID,"Warning: unsupported instruction set processing atom packet."));
1344              // wait for next context
1345              return OCSD_OK;
1346         }
1347         else
1348         {
1349             err = handlePacketSeqErr(err, pElem->getRootIndex(), "Error processing atom packet.");
1350             //LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,pElem->getRootIndex(),m_CSID,"Error processing atom packet."));
1351             return err;
1352         }
1353     }
1354 
1355     if(WPFound(WPRes))
1356     {
1357         //  save recorded next instuction address
1358         ocsd_vaddr_t nextAddr = m_instr_info.instr_addr;
1359 
1360         // action according to waypoint type and atom value
1361         switch(m_instr_info.type)
1362         {
1363         case OCSD_INSTR_BR:
1364             if (atom == ATOM_E)
1365             {
1366                 m_instr_info.instr_addr = m_instr_info.branch_addr;
1367                 if (m_instr_info.is_link)
1368                     m_return_stack.push(nextAddr, m_instr_info.isa);
1369 
1370             }
1371             else if (m_direct_br_chk || m_strict_br_chk)  // consistency checks on N atoms?
1372             {
1373                 // N atom - but direct branch instruction not conditional - bad input image?
1374                 if (!m_instr_info.is_conditional)
1375                 {
1376                     // Some ETM IP incorrectly trace a taken branch to next instruction as N
1377                     // look for branch where it is not next instruction if direct branch checks only
1378                     if (((m_instr_info.branch_addr != nextAddr) && m_direct_br_chk) || m_strict_br_chk)
1379                     {
1380                         err = handleBadImageError(pElem->getRootIndex(), "Bad program image - N Atom on unconditional direct BR.\n");
1381                         return err;
1382                     }
1383                 }
1384             }
1385             break;
1386 
1387         case OCSD_INSTR_BR_INDIRECT:
1388             if (atom == ATOM_E)
1389             {
1390                 m_need_addr = true; // indirect branch taken - need new address.
1391                 if (m_instr_info.is_link)
1392                     m_return_stack.push(nextAddr,m_instr_info.isa);
1393 
1394                 // mark last atom as BR indirect - if no address next need addr from return stack.
1395                 m_return_stack.set_pop_pending();
1396 
1397                 /* ETE does not have ERET trace packets - however to maintain the illusion if we see an ERET
1398                    output a gen elem ERET packet */
1399                 if (isETEConfig() && (m_instr_info.sub_type == OCSD_S_INSTR_V8_ERET))
1400                     ETE_ERET = true;
1401             }
1402             else if (m_strict_br_chk) // consistency checks on N atoms?
1403             {
1404                 // N atom - check if conditional - only in strict check mode.
1405                 if (!m_instr_info.is_conditional)
1406                 {
1407                     err = handleBadImageError(pElem->getRootIndex(), "Bad program image - N Atom on unconditional indirect BR.\n");
1408                     return err;
1409                 }
1410             }
1411             break;
1412         }
1413         setElemTraceRange(outElem(), addr_range, (atom == ATOM_E), pElem->getRootIndex());
1414 
1415         // check for discontinuity in address ranges where incorrect memory images supplied to decoder.
1416         if (m_range_cont_chk)
1417         {
1418             // do the previous range chack.
1419             if (!nextRangeCheckOK(addr_range.st_addr))
1420             {
1421                 err = handleBadImageError(pElem->getRootIndex(), "Discontinuous ranges - Inconsistent program image for decode\n");
1422                 return err;
1423             }
1424 
1425             if (atom == ATOM_N)
1426                 // branch not taken - expect next range to be continuous
1427                 nextRangeCheckSet(nextAddr);
1428             else
1429                 nextRangeCheckClear();  // branch taken - not continuous
1430         }
1431 
1432         if (ETE_ERET)
1433         {
1434             err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_EXCEPTION_RET);
1435             if (err)
1436                 return err;
1437         }
1438     }
1439     else
1440     {
1441         // no waypoint - likely inaccessible memory range.
1442         m_need_addr = true; // need an address update
1443         nextRangeCheckClear();
1444 
1445         if(addr_range.st_addr != addr_range.en_addr)
1446         {
1447             // some trace before we were out of memory access range
1448             setElemTraceRange(outElem(), addr_range, true, pElem->getRootIndex());
1449 
1450             // another element for the nacc...
1451             if (WPNacc(WPRes))
1452                 err = m_out_elem.addElem(pElem->getRootIndex());
1453         }
1454 
1455         if(WPNacc(WPRes) && !err)
1456         {
1457             outElem().setType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
1458             outElem().st_addr = m_instr_info.instr_addr;
1459             outElem().exception_number = (uint32_t)getCurrMemSpace();
1460         }
1461     }
1462     return err;
1463 }
1464 
1465 // Exception processor
1466 #define M_CLASS_TAIL_ADDR 0xFFFFFFFE
1467 
processException()1468 ocsd_err_t TrcPktDecodeEtmV4I::processException()
1469 {
1470     ocsd_err_t err;
1471     TrcStackElem *pElem = 0;
1472     TrcStackElemExcept *pExceptElem = 0;
1473     TrcStackElemAddr *pAddressElem = 0;
1474     TrcStackElemCtxt *pCtxtElem = 0;
1475     bool branch_target = false;    // exception address implies prior branch target address
1476     ocsd_vaddr_t excep_ret_addr = 0;
1477     ocsd_trc_index_t excep_pkt_index;
1478     WP_res_t WPRes = WP_NOT_FOUND;
1479     bool ETE_resetPkt = false;
1480     bool bMTailChain = false;
1481 
1482     // grab the exception element off the stack
1483     pExceptElem = dynamic_cast<TrcStackElemExcept *>(m_P0_stack.back());  // get the exception element
1484     excep_pkt_index = pExceptElem->getRootIndex();
1485     branch_target = pExceptElem->getPrevSame();
1486     if (pExceptElem->getRootPkt() == ETE_PKT_I_PE_RESET)
1487         ETE_resetPkt = true;
1488     m_P0_stack.pop_back(); // remove the exception element
1489 
1490     // ETE reset has no follow up address, the rest of the exceptions do....
1491     if (!ETE_resetPkt)
1492     {
1493         pElem = m_P0_stack.back();  // look at next element.
1494         if (pElem->getP0Type() == P0_CTXT)
1495         {
1496             pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem);
1497             m_P0_stack.pop_back(); // remove the context element
1498             pElem = m_P0_stack.back();  // next one should be an address element
1499         }
1500 
1501         if (pElem->getP0Type() != P0_ADDR)
1502         {
1503             // no following address element - indicate processing error.
1504 
1505             err = handlePacketSeqErr(OCSD_ERR_BAD_PACKET_SEQ, m_index_curr_pkt, "Address missing in exception packet.");
1506             //LogError(ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_BAD_PACKET_SEQ, excep_pkt_index, m_CSID, "Address missing in exception packet."));
1507             return err;
1508         }
1509         else
1510         {
1511             // extract address
1512             pAddressElem = static_cast<TrcStackElemAddr *>(pElem);
1513             excep_ret_addr = pAddressElem->getAddr().val;
1514 
1515             // see if there is an address + optional context element implied
1516             // prior to the exception.
1517             if (branch_target)
1518             {
1519                 // this was a branch target address - update current setting
1520                 bool b64bit = m_instr_info.isa == ocsd_isa_aarch64;
1521                 if (pCtxtElem) {
1522                     b64bit = pCtxtElem->getContext().SF;
1523                 }
1524 
1525                 // as the exception address was also a branch target address then update the
1526                 // current maintained address value. This also means that there is no range to
1527                 // output before the exception packet.
1528                 m_instr_info.instr_addr = excep_ret_addr;
1529                 m_instr_info.isa = (pAddressElem->getAddr().isa == 0) ?
1530                     (b64bit ? ocsd_isa_aarch64 : ocsd_isa_arm) : ocsd_isa_thumb2;
1531                 m_need_addr = false;
1532             }
1533         }
1534     }
1535 
1536     // need to output something - set up an element
1537     if ((err = m_out_elem.addElem(excep_pkt_index)))
1538         return err;
1539 
1540     // output a context element if present
1541     if (pCtxtElem)
1542     {
1543         updateContext(pCtxtElem, outElem());
1544 
1545         // used the element - need another for later stages
1546         if ((err = m_out_elem.addElem(excep_pkt_index)))
1547             return err;
1548     }
1549 
1550     if (!ETE_resetPkt)
1551     {
1552         /* check for M class tail chain / deferred exceptions */
1553         if (m_config->coreProfile() == profile_CortexM)
1554             bMTailChain = (excep_ret_addr == M_CLASS_TAIL_ADDR);
1555 
1556         // if the preferred return address is not the end of the last output range...
1557         if ((m_instr_info.instr_addr < excep_ret_addr) && !bMTailChain)
1558         {
1559             bool range_out = false;
1560             instr_range_t addr_range;
1561 
1562             // look for match to return address.
1563             err = traceInstrToWP(addr_range, WPRes, true, excep_ret_addr);
1564 
1565             if (err != OCSD_OK)
1566             {
1567                 if (err == OCSD_ERR_UNSUPPORTED_ISA)
1568                 {
1569                     m_need_addr = true;
1570                     m_need_ctxt = true;
1571                     LogError(ocsdError(OCSD_ERR_SEV_WARN, err, excep_pkt_index, m_CSID, "Warning: unsupported instruction set processing exception packet."));
1572                 }
1573                 else
1574                 {
1575                     LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, excep_pkt_index, m_CSID, "Error processing exception packet."));
1576                 }
1577                 return err;
1578             }
1579 
1580             if (WPFound(WPRes))
1581             {
1582                 // waypoint address found - output range
1583                 setElemTraceRange(outElem(), addr_range, true, excep_pkt_index);
1584                 range_out = true;
1585             }
1586             else
1587             {
1588                 // no waypoint - likely inaccessible memory range.
1589                 m_need_addr = true; // need an address update
1590 
1591                 if (addr_range.st_addr != addr_range.en_addr)
1592                 {
1593                     // some trace before we were out of memory access range
1594                     setElemTraceRange(outElem(), addr_range, true, excep_pkt_index);
1595                     range_out = true;
1596                 }
1597             }
1598 
1599             // used the element need another for NACC or EXCEP.
1600             if (range_out)
1601             {
1602                 if ((err = m_out_elem.addElem(excep_pkt_index)))
1603                     return err;
1604             }
1605         }
1606 
1607         // watchpoint walk resulted in inaccessible memory call...
1608         if (WPNacc(WPRes))
1609         {
1610 
1611             outElem().setType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
1612             outElem().st_addr = m_instr_info.instr_addr;
1613             outElem().exception_number = (uint32_t)getCurrMemSpace();
1614 
1615             // used the element - need another for the final exception packet.
1616             if ((err = m_out_elem.addElem(excep_pkt_index)))
1617                 return err;
1618         }
1619     }
1620 
1621     // output exception element.
1622     outElem().setType(OCSD_GEN_TRC_ELEM_EXCEPTION);
1623 
1624     // add end address as preferred return address to end addr in element
1625     outElem().en_addr = excep_ret_addr;
1626 
1627     outElem().excep_ret_addr = 1;
1628     if (bMTailChain)
1629     {
1630         outElem().excep_ret_addr = 0;
1631         outElem().excep_M_tail_chain = 1;
1632     }
1633     outElem().excep_ret_addr_br_tgt = branch_target;
1634     outElem().exception_number = pExceptElem->getExcepNum();
1635 
1636     m_P0_stack.delete_popped();     // clear the used elements from the stack
1637     return err;
1638 }
1639 
processQElement()1640 ocsd_err_t TrcPktDecodeEtmV4I::processQElement()
1641 {
1642     ocsd_err_t err = OCSD_OK;
1643     TrcStackQElem *pQElem;
1644     etmv4_addr_val_t QAddr; // address where trace restarts
1645     int iCount = 0;
1646 
1647     pQElem = dynamic_cast<TrcStackQElem *>(m_P0_stack.back());  // get the exception element
1648     m_P0_stack.pop_back(); // remove the Q element.
1649 
1650     if (!pQElem->hasAddr())  // no address - it must be next on the stack....
1651     {
1652         TrcStackElemAddr *pAddressElem = 0;
1653         TrcStackElemCtxt *pCtxtElem = 0;
1654         TrcStackElem *pElem = 0;
1655 
1656         pElem = m_P0_stack.back();  // look at next element.
1657         if (pElem->getP0Type() == P0_CTXT)
1658         {
1659             pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem);
1660             m_P0_stack.pop_back(); // remove the context element
1661             pElem = m_P0_stack.back();  // next one should be an address element
1662         }
1663 
1664         if (pElem->getP0Type() != P0_ADDR)
1665         {
1666             // no following address element - indicate processing error.
1667             err = OCSD_ERR_BAD_PACKET_SEQ;
1668             LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pQElem->getRootIndex(), m_CSID, "Address missing in Q packet."));
1669             m_P0_stack.delete_popped();
1670             return err;
1671         }
1672         pAddressElem = dynamic_cast<TrcStackElemAddr *>(pElem);
1673         QAddr = pAddressElem->getAddr();
1674         m_P0_stack.pop_back();  // remove the address element
1675         m_P0_stack.delete_popped(); // clear used elements
1676 
1677         // return the context element for processing next time.
1678         if (pCtxtElem)
1679         {
1680             // need a new copy at the back - old one will be deleted as popped.
1681             m_P0_stack.createContextElem(pCtxtElem->getRootPkt(), pCtxtElem->getRootIndex(), pCtxtElem->getContext(),true);
1682         }
1683     }
1684     else
1685         QAddr = pQElem->getAddr();
1686 
1687     // process the Q element with address.
1688     iCount = pQElem->getInstrCount();
1689 
1690     bool isBranch = false;
1691 
1692     // need to output something - set up an element
1693     if ((err = m_out_elem.addElem(pQElem->getRootIndex())))
1694         return err;
1695 
1696     instr_range_t addr_range;
1697     addr_range.st_addr = addr_range.en_addr = m_instr_info.instr_addr;
1698     addr_range.num_instr = 0;
1699 
1700     // walk iCount instructions
1701     for (int i = 0; i < iCount; i++)
1702     {
1703         uint32_t opcode;
1704         uint32_t bytesReq = 4;
1705 
1706         err = accessMemory(m_instr_info.instr_addr, getCurrMemSpace(), &bytesReq, (uint8_t *)&opcode);
1707         if (err != OCSD_OK) break;
1708 
1709         if (bytesReq == 4) // got data back
1710         {
1711             m_instr_info.opcode = opcode;
1712             err = instrDecode(&m_instr_info);
1713             if (err != OCSD_OK) break;
1714 
1715             // increment address - may be adjusted by direct branch value later
1716             m_instr_info.instr_addr += m_instr_info.instr_size;
1717             addr_range.num_instr++;
1718 
1719             isBranch = (m_instr_info.type == OCSD_INSTR_BR) ||
1720                 (m_instr_info.type == OCSD_INSTR_BR_INDIRECT);
1721 
1722             // on a branch no way of knowing if taken - bail out
1723             if (isBranch)
1724                 break;
1725         }
1726         else
1727             break;  // missing memory
1728 
1729     }
1730 
1731     if (err == OCSD_OK)
1732     {
1733         bool inCompleteRange = true;
1734         if (iCount && (addr_range.num_instr == (unsigned)iCount))
1735         {
1736             if ((m_instr_info.instr_addr == QAddr.val) ||    // complete range
1737                 (isBranch)) // or ends on branch - only way we know if branch taken.
1738             {
1739                 // output a range and continue
1740                 inCompleteRange = false;
1741                 // update the range decoded address in the output packet.
1742                 addr_range.en_addr = m_instr_info.instr_addr;
1743                 setElemTraceRange(outElem(), addr_range, true, pQElem->getRootIndex());
1744             }
1745         }
1746 
1747         if (inCompleteRange)
1748         {
1749             // unknown instructions executed.
1750             addr_range.en_addr = QAddr.val;
1751             addr_range.num_instr = iCount;
1752 
1753             outElem().setType(OCSD_GEN_TRC_ELEM_I_RANGE_NOPATH);
1754             outElem().setAddrRange(addr_range.st_addr, addr_range.en_addr, addr_range.num_instr);
1755             outElem().setISA(calcISA(m_is_64bit, QAddr.isa));
1756         }
1757 
1758         // after the Q element, tracing resumes at the address supplied
1759         SetInstrInfoInAddrISA(QAddr.val, QAddr.isa);
1760         m_need_addr = false;
1761     }
1762     else
1763     {
1764         // output error and halt decode.
1765         LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pQElem->getRootIndex(), m_CSID, "Error processing Q packet"));
1766     }
1767     m_P0_stack.delete_popped();
1768     return err;
1769 }
1770 
processSourceAddress()1771 ocsd_err_t TrcPktDecodeEtmV4I::processSourceAddress()
1772 {
1773     ocsd_err_t err = OCSD_OK;
1774     TrcStackElemAddr *pElem = dynamic_cast<TrcStackElemAddr *>(m_P0_stack.back());  // get the address element
1775     etmv4_addr_val_t srcAddr = pElem->getAddr();
1776     uint32_t opcode, bytesReq = 4;
1777     ocsd_vaddr_t currAddr = m_instr_info.instr_addr;    // get the latest decoded address.
1778     instr_range_t out_range;
1779     bool bSplitRangeOnN = getComponentOpMode() & ETE_OPFLG_PKTDEC_SRCADDR_N_ATOMS ? true : false;
1780 
1781     // check we can read instruction @ source address
1782     err = accessMemory(srcAddr.val, getCurrMemSpace(), &bytesReq, (uint8_t *)&opcode);
1783     if (err != OCSD_OK)
1784     {
1785         LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pElem->getRootIndex(), m_CSID, "Mem access error processing source address packet."));
1786         return err;
1787     }
1788 
1789     if (bytesReq != 4)
1790     {
1791         // can't access - no bytes returned - output nacc.
1792         err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_ADDR_NACC);
1793         outElem().setAddrStart(srcAddr.val);
1794         outElem().exception_number = (uint32_t)getCurrMemSpace();
1795         return err;
1796     }
1797 
1798     // analyze opcode @ source address.
1799     m_instr_info.opcode = opcode;
1800     m_instr_info.instr_addr = srcAddr.val;
1801     err = instrDecode(&m_instr_info);
1802     if (err != OCSD_OK)
1803     {
1804         LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pElem->getRootIndex(), m_CSID, "Instruction decode error processing source address packet."));
1805         return err;
1806     }
1807     m_instr_info.instr_addr += m_instr_info.instr_size;
1808 
1809     // initial instruction count for the range.
1810     out_range.num_instr = 1;
1811 
1812     // calculate range traced...
1813     if (m_need_addr || (currAddr > srcAddr.val))
1814     {
1815         // we were waiting for a target address, or missing trace
1816         // that indicates how we got to the source address.
1817         m_need_addr = false;
1818         out_range.st_addr = srcAddr.val;
1819     }
1820     else
1821         out_range.st_addr = currAddr;
1822     out_range.en_addr = m_instr_info.instr_addr;
1823 
1824     // count instructions
1825     if (out_range.en_addr - out_range.st_addr > m_instr_info.instr_size)
1826     {
1827         if ((m_instr_info.isa != ocsd_isa_thumb2) && !bSplitRangeOnN)
1828         {
1829             // all 4 byte instructions - just calculate...
1830             out_range.num_instr = (uint32_t)(out_range.en_addr - out_range.st_addr) / 4;
1831         }
1832         else
1833         {
1834             // need to count T32 - 2 or 4 byte instructions or we are spotting N atoms
1835             ocsd_instr_info instr; // going back to start of range so make a copy of info.
1836             bool bMemAccErr = false;
1837 
1838             instr.instr_addr = out_range.st_addr;
1839             instr.isa = m_instr_info.isa;
1840             instr.pe_type = m_instr_info.pe_type;
1841             instr.dsb_dmb_waypoints = m_instr_info.dsb_dmb_waypoints;
1842             instr.wfi_wfe_branch = m_instr_info.wfi_wfe_branch;
1843             out_range.num_instr = 0;
1844 
1845             while ((instr.instr_addr < out_range.en_addr) && !bMemAccErr)
1846             {
1847                 bytesReq = 4;
1848                 err = accessMemory(instr.instr_addr, getCurrMemSpace(), &bytesReq, (uint8_t *)&opcode);
1849                 if (err != OCSD_OK)
1850                 {
1851                     LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pElem->getRootIndex(), m_CSID, "Mem access error processing source address packet."));
1852                     return err;
1853                 }
1854 
1855                 if (bytesReq == 4)
1856                 {
1857                     instr.opcode = opcode;
1858                     err = instrDecode(&instr);
1859                     if (err != OCSD_OK)
1860                     {
1861                         LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pElem->getRootIndex(), m_CSID, "Instruction decode error processing source address packet."));
1862                         return err;
1863                     }
1864 
1865                     instr.instr_addr += instr.instr_size;
1866                     out_range.num_instr++;
1867 
1868                     /* if we are doing N atom ranges ...*/
1869                     if (bSplitRangeOnN && (instr.instr_addr < out_range.en_addr))
1870                     {
1871                         if (instr.type != OCSD_INSTR_OTHER)
1872                         {
1873                             instr_range_t mid_range = out_range;
1874                             mid_range.en_addr = instr.instr_addr;
1875 
1876                             err = m_out_elem.addElem(pElem->getRootIndex());
1877                             if (err)
1878                                 return err;
1879                             setElemTraceRangeInstr(outElem(), mid_range, false, pElem->getRootIndex(), instr);
1880 
1881                             out_range.st_addr = mid_range.en_addr;
1882                             out_range.num_instr = 0;
1883                         }
1884                     }
1885                 }
1886                 else
1887                 {
1888                     // something inaccessible between last and current...
1889                     bMemAccErr = true;
1890 
1891                     err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_ADDR_NACC);
1892                     if (err)
1893                         return err;
1894                     outElem().setAddrStart(srcAddr.val);
1895                     outElem().exception_number = (uint32_t)getCurrMemSpace();
1896 
1897                     // force range to the one instruction
1898                     out_range.num_instr = 1;
1899                     out_range.st_addr = srcAddr.val;
1900                     out_range.en_addr = m_instr_info.instr_addr;  // instr after the decoded instruction @ srcAddr.
1901                 }
1902             }
1903         }
1904     }
1905 
1906     // got to the source address - output trace range, and instruction as E atom.
1907     switch (m_instr_info.type)
1908     {
1909     case OCSD_INSTR_BR:
1910         if (m_instr_info.is_link)
1911             m_return_stack.push(m_instr_info.instr_addr, m_instr_info.isa);
1912         m_instr_info.instr_addr = m_instr_info.branch_addr;
1913         break;
1914 
1915     case OCSD_INSTR_BR_INDIRECT:
1916         m_need_addr = true; // indirect branch taken - need new address.
1917         if (m_instr_info.is_link)
1918             m_return_stack.push(m_instr_info.instr_addr, m_instr_info.isa);
1919         m_return_stack.set_pop_pending();  // need to know next packet before we know what is to happen
1920         break;
1921     }
1922     m_instr_info.isa = m_instr_info.next_isa;
1923 
1924     // set the trace range element.
1925     m_out_elem.addElem(pElem->getRootIndex());
1926     setElemTraceRange(outElem(), out_range, true, pElem->getRootIndex());
1927     return err;
1928 }
1929 
SetInstrInfoInAddrISA(const ocsd_vaddr_t addr_val,const uint8_t isa)1930 void TrcPktDecodeEtmV4I::SetInstrInfoInAddrISA(const ocsd_vaddr_t addr_val, const uint8_t isa)
1931 {
1932     m_instr_info.instr_addr = addr_val;
1933     m_instr_info.isa = calcISA(m_is_64bit, isa);
1934 }
1935 
1936 // trace an instruction range to a waypoint - and set next address to restart from.
traceInstrToWP(instr_range_t & range,WP_res_t & WPRes,const bool traceToAddrNext,const ocsd_vaddr_t nextAddrMatch)1937 ocsd_err_t TrcPktDecodeEtmV4I::traceInstrToWP(instr_range_t &range, WP_res_t &WPRes, const bool traceToAddrNext /*= false*/, const ocsd_vaddr_t nextAddrMatch /*= 0*/)
1938 {
1939     uint32_t opcode;
1940     uint32_t bytesReq;
1941     ocsd_err_t err = OCSD_OK;
1942 
1943     range.st_addr = range.en_addr = m_instr_info.instr_addr;
1944     range.num_instr = 0;
1945 
1946     WPRes = WP_NOT_FOUND;
1947 
1948     while(WPRes == WP_NOT_FOUND)
1949     {
1950         // start off by reading next opcode;
1951         bytesReq = 4;
1952         err = accessMemory(m_instr_info.instr_addr, getCurrMemSpace(),&bytesReq,(uint8_t *)&opcode);
1953         if(err != OCSD_OK) break;
1954 
1955         if(bytesReq == 4) // got data back
1956         {
1957             m_instr_info.opcode = opcode;
1958             err = instrDecode(&m_instr_info);
1959             if(err != OCSD_OK) break;
1960 
1961             // increment address - may be adjusted by direct branch value later
1962             m_instr_info.instr_addr += m_instr_info.instr_size;
1963             range.num_instr++;
1964 
1965             // either walking to match the next instruction address or a real watchpoint
1966             if (traceToAddrNext)
1967             {
1968                 if (m_instr_info.instr_addr == nextAddrMatch)
1969                     WPRes = WP_FOUND;
1970             }
1971             else if (m_instr_info.type != OCSD_INSTR_OTHER)
1972                 WPRes = WP_FOUND;
1973         }
1974         else
1975         {
1976             // not enough memory accessible.
1977             WPRes = WP_NACC;
1978         }
1979 
1980         if (m_num_instr_range_limit)
1981         {
1982             if (range.num_instr > (uint32_t)m_num_instr_range_limit)
1983             {
1984                 err = OCSD_ERR_I_RANGE_LIMIT_OVERRUN;
1985                 LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, "Decode Instruction Range Limit Overrun"));
1986             }
1987         }
1988     }
1989     // update the range decoded address in the output packet.
1990     range.en_addr = m_instr_info.instr_addr;
1991     return err;
1992 }
1993 
updateContext(TrcStackElemCtxt * pCtxtElem,OcsdTraceElement & elem)1994 void TrcPktDecodeEtmV4I::updateContext(TrcStackElemCtxt *pCtxtElem, OcsdTraceElement &elem)
1995 {
1996     etmv4_context_t ctxt = pCtxtElem->getContext();
1997 
1998     elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT);
1999 
2000     // map to output element and local saved state.
2001     m_is_64bit = (ctxt.SF != 0);
2002     elem.context.bits64 = ctxt.SF;
2003     m_is_secure = (ctxt.NS == 0);
2004     if (ctxt.NSE)
2005         elem.context.security_level = ctxt.NS ? ocsd_sec_realm : ocsd_sec_root;
2006     else
2007         elem.context.security_level = ctxt.NS ? ocsd_sec_nonsecure : ocsd_sec_secure;
2008     elem.context.exception_level = (ocsd_ex_level)ctxt.EL;
2009     elem.context.el_valid = 1;
2010     if(ctxt.updated_c)
2011     {
2012         elem.context.ctxt_id_valid = 1;
2013         m_context_id = elem.context.context_id = ctxt.ctxtID;
2014     }
2015     if(ctxt.updated_v)
2016     {
2017         elem.context.vmid_valid = 1;
2018         m_vmid_id = elem.context.vmid = ctxt.VMID;
2019     }
2020 
2021     // need to update ISA in case context follows address.
2022     elem.isa = m_instr_info.isa = calcISA(m_is_64bit, pCtxtElem->getIS());
2023     m_need_ctxt = false;
2024 }
2025 
handleBadPacket(const char * reason,ocsd_trc_index_t index)2026 ocsd_err_t TrcPktDecodeEtmV4I::handleBadPacket(const char *reason, ocsd_trc_index_t index /* = OCSD_BAD_TRC_INDEX */)
2027 {
2028     ocsd_err_severity_t sev = OCSD_ERR_SEV_WARN;
2029     if (getComponentOpMode() & OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS)
2030         sev = OCSD_ERR_SEV_ERROR;
2031 
2032     return handlePacketErr(OCSD_ERR_BAD_DECODE_PKT, sev, index, reason, UNSYNC_BAD_PACKET);
2033 }
2034 
handlePacketSeqErr(ocsd_err_t err,ocsd_trc_index_t index,const char * reason)2035 ocsd_err_t TrcPktDecodeEtmV4I::handlePacketSeqErr(ocsd_err_t err, ocsd_trc_index_t index, const char *reason)
2036 {
2037     return handlePacketErr(err, OCSD_ERR_SEV_ERROR, index, reason, UNSYNC_BAD_PACKET);
2038 }
2039 
handleBadImageError(ocsd_trc_index_t index,const char * reason)2040 ocsd_err_t TrcPktDecodeEtmV4I::handleBadImageError(ocsd_trc_index_t index, const char* reason)
2041 {
2042     return handlePacketErr(OCSD_ERR_BAD_DECODE_IMAGE, OCSD_ERR_SEV_ERROR, index, reason, UNSYNC_BAD_IMAGE);
2043 }
2044 
handlePacketErr(ocsd_err_t err,ocsd_err_severity_t sev,ocsd_trc_index_t index,const char * reason,const unsync_info_t unsync_reason)2045 ocsd_err_t TrcPktDecodeEtmV4I::handlePacketErr(ocsd_err_t err, ocsd_err_severity_t sev, ocsd_trc_index_t index, const char *reason, const unsync_info_t unsync_reason)
2046 {
2047     bool resetOnBadPackets = true;
2048 
2049     if(getComponentOpMode() & OCSD_OPFLG_PKTDEC_HALT_BAD_PKTS)
2050         resetOnBadPackets = false;
2051 
2052     LogError(ocsdError(sev, err, index, getCoreSightTraceID(), reason));
2053 
2054     if (resetOnBadPackets)
2055     {
2056         // switch to unsync - clear decode state
2057         resetDecoder();
2058         m_curr_state = NO_SYNC;
2059         m_unsync_eot_info = unsync_reason;
2060         //err = OCSD_OK;
2061     }
2062     return err;
2063 
2064 }
2065 
getCurrMemSpace()2066 inline ocsd_mem_space_acc_t TrcPktDecodeEtmV4I::getCurrMemSpace()
2067 {
2068     static ocsd_mem_space_acc_t SMemSpace[] = {
2069         OCSD_MEM_SPACE_EL1S,
2070         OCSD_MEM_SPACE_EL1S,
2071         OCSD_MEM_SPACE_EL2S,
2072         OCSD_MEM_SPACE_EL3
2073     };
2074 
2075     static ocsd_mem_space_acc_t NSMemSpace[] = {
2076         OCSD_MEM_SPACE_EL1N,
2077         OCSD_MEM_SPACE_EL1N,
2078         OCSD_MEM_SPACE_EL2,
2079         OCSD_MEM_SPACE_EL3
2080     };
2081 
2082     static ocsd_mem_space_acc_t RMemSpace[] = {
2083         OCSD_MEM_SPACE_EL1R,
2084         OCSD_MEM_SPACE_EL1R,
2085         OCSD_MEM_SPACE_EL2R,
2086         OCSD_MEM_SPACE_ROOT
2087     };
2088 
2089     /* if no valid EL value - just use S/NS */
2090     if (!outElem().context.el_valid)
2091         return  m_is_secure ? OCSD_MEM_SPACE_S : OCSD_MEM_SPACE_N;
2092 
2093     /* mem space according to EL + S/NS */
2094     ocsd_mem_space_acc_t mem_space = OCSD_MEM_SPACE_NONE;
2095     int el = (int)(outElem().context.exception_level) & 0x3;
2096 
2097     switch (outElem().context.security_level)
2098     {
2099     case ocsd_sec_root:
2100         mem_space = OCSD_MEM_SPACE_ROOT;
2101         break;
2102     case ocsd_sec_realm:
2103         mem_space = RMemSpace[el];
2104         break;
2105     case ocsd_sec_nonsecure:
2106         mem_space = NSMemSpace[el];
2107         break;
2108     case ocsd_sec_secure:
2109         mem_space = SMemSpace[el];
2110         break;
2111     };
2112 
2113     return mem_space;
2114 }
2115 /* End of File trc_pkt_decode_etmv4i.cpp */
2116