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