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.", m_index_curr_pkt);
481 break;
482
483 case ETM4_PKT_I_BAD_TRACEMODE:
484 err = handleBadPacket("Invalid packet type for trace mode.", m_index_curr_pkt);
485 break;
486
487 case ETM4_PKT_I_RESERVED:
488 err = handleBadPacket("Reserved packet header", m_index_curr_pkt);
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 err = handlePacketSeqErr(err, m_index_curr_pkt, "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 if (sev == OCSD_ERR_SEV_WARN)
596 LogError(ocsdError(sev, err, "Data trace related, unsupported packet type."));
597 else
598 err = handlePacketSeqErr(err, m_index_curr_pkt, "Data trace related, unsupported packet type.");
599 }
600 break;
601
602 default:
603 // any other packet - bad packet error
604 err = handleBadPacket("Unknown packet type.", m_index_curr_pkt);
605 break;
606 }
607
608 // we need to wait for following address after certain packets
609 // - work out if we have seen enough here...
610 if (is_addr && m_elem_pending_addr)
611 {
612 m_curr_spec_depth++; // increase spec depth for element waiting on address.
613 m_elem_pending_addr = false; // can't be waiting on both
614 }
615
616 if(bAllocErr)
617 {
618 err = OCSD_ERR_MEM;
619 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_MEM,"Memory allocation error."));
620 }
621 else if(m_curr_spec_depth > m_max_spec_depth)
622 {
623 // auto commit anything above max spec depth
624 // (this will auto commit anything if spec depth not supported!)
625 m_elem_res.P0_commit = m_curr_spec_depth - m_max_spec_depth;
626 }
627
628 if (!err && isElemForRes())
629 m_curr_state = RESOLVE_ELEM;
630 return err;
631 }
632
doTraceInfoPacket()633 void TrcPktDecodeEtmV4I::doTraceInfoPacket()
634 {
635 m_trace_info = m_curr_packet_in->getTraceInfo();
636 m_cc_threshold = m_curr_packet_in->getCCThreshold();
637 m_curr_spec_depth = m_curr_packet_in->getCurrSpecDepth();
638 /* put a trans marker in stack if started in trans state */
639 if (m_trace_info.bits.in_trans_state)
640 m_P0_stack.createParamElemNoParam(P0_TRANS_TRACE_INIT, false, m_curr_packet_in->getType(), m_index_curr_pkt);
641
642 // elements associated with data trace
643 #ifdef DATA_TRACE_SUPPORTED
644 m_p0_key = m_curr_packet_in->getP0Key();
645 #endif
646 }
647
648 /* Element resolution
649 * Commit or cancel elements as required
650 * Send any buffered output packets.
651 */
resolveElements()652 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::resolveElements()
653 {
654 ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
655 bool Complete = false;
656
657 while (!Complete)
658 {
659 if (m_out_elem.numElemToSend())
660 resp = m_out_elem.sendElements();
661 else if (isElemForRes())
662 {
663 ocsd_err_t err = OCSD_OK;
664 if (m_elem_res.P0_commit)
665 err = commitElements();
666
667 if (!err && m_elem_res.P0_cancel)
668 err = cancelElements();
669
670 if (!err && m_elem_res.mispredict)
671 err = mispredictAtom();
672
673 if (!err && m_elem_res.discard)
674 err = discardElements();
675
676 if (err != OCSD_OK)
677 resp = OCSD_RESP_FATAL_INVALID_DATA;
678 }
679
680 // break out on error or wait request.
681 if (!OCSD_DATA_RESP_IS_CONT(resp))
682 break;
683
684 // completion is nothing to send and nothing to commit
685 Complete = !m_out_elem.numElemToSend() && !isElemForRes();
686
687 // done all elements - need more packets.
688 if (Complete) {
689 // if we are still in resolve, the goto decode.
690 if (m_curr_state == RESOLVE_ELEM)
691 m_curr_state = DECODE_PKTS;
692 }
693 }
694 return resp;
695 }
696
697 /*
698 * Walks through the element stack, processing from oldest element to the newest,
699 according to the number of P0 elements that need committing.
700 Build a stack of output elements in the process.
701 */
commitElements()702 ocsd_err_t TrcPktDecodeEtmV4I::commitElements()
703 {
704 ocsd_err_t err = OCSD_OK;
705 bool bPopElem = true; // do we remove the element from the stack (multi atom elements may need to stay!)
706 int num_commit_req = m_elem_res.P0_commit;
707 ocsd_trc_index_t err_idx = 0;
708 TrcStackElem *pElem = 0; // stacked element pointer
709
710 err = m_out_elem.resetElemStack();
711
712 while(m_elem_res.P0_commit && !err)
713 {
714 if (m_P0_stack.size() > 0)
715 {
716 pElem = m_P0_stack.back(); // get oldest element
717 err_idx = pElem->getRootIndex(); // save index in case of error.
718
719 switch (pElem->getP0Type())
720 {
721 // indicates a trace restart - beginning of trace or discontinuiuty
722 case P0_TRC_ON:
723 err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_TRACE_ON);
724 if (!err)
725 {
726 m_out_elem.getCurrElem().trace_on_reason = m_prev_overflow ? TRACE_ON_OVERFLOW : TRACE_ON_NORMAL;
727 m_prev_overflow = false;
728 m_return_stack.flush();
729 }
730 break;
731
732 case P0_ADDR:
733 {
734 TrcStackElemAddr *pAddrElem = dynamic_cast<TrcStackElemAddr *>(pElem);
735 m_return_stack.clear_pop_pending(); // address removes the need to pop the indirect address target from the stack
736 if (pAddrElem)
737 {
738 SetInstrInfoInAddrISA(pAddrElem->getAddr().val, pAddrElem->getAddr().isa);
739 m_need_addr = false;
740 }
741 }
742 break;
743
744 case P0_CTXT:
745 {
746 TrcStackElemCtxt *pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem);
747 if (pCtxtElem)
748 {
749 etmv4_context_t ctxt = pCtxtElem->getContext();
750 // check this is an updated context
751 if(ctxt.updated)
752 {
753 err = m_out_elem.addElem(pElem->getRootIndex());
754 if (!err)
755 updateContext(pCtxtElem, outElem());
756 }
757 }
758 }
759 break;
760
761 case P0_EVENT:
762 case P0_TS:
763 case P0_CC:
764 case P0_TS_CC:
765 err = processTS_CC_EventElem(pElem);
766 break;
767
768 case P0_MARKER:
769 err = processMarkerElem(pElem);
770 break;
771
772 case P0_ATOM:
773 {
774 TrcStackElemAtom *pAtomElem = dynamic_cast<TrcStackElemAtom *>(pElem);
775
776 if (pAtomElem)
777 {
778 while(!pAtomElem->isEmpty() && m_elem_res.P0_commit && !err)
779 {
780 ocsd_atm_val atom = pAtomElem->commitOldest();
781
782 // check if prev atom left us an indirect address target on the return stack
783 if ((err = returnStackPop()) != OCSD_OK)
784 break;
785
786 // if address and context do instruction trace follower.
787 // otherwise skip atom and reduce committed elements
788 if (!m_need_ctxt && !m_need_addr)
789 {
790 err = processAtom(atom);
791 }
792 m_elem_res.P0_commit--; // mark committed
793 }
794 if (!pAtomElem->isEmpty())
795 bPopElem = false; // don't remove if still atoms to process.
796 }
797 }
798 break;
799
800 case P0_EXCEP:
801 // check if prev atom left us an indirect address target on the return stack
802 if ((err = returnStackPop()) != OCSD_OK)
803 break;
804
805 err = processException(); // output trace + exception elements.
806 m_elem_res.P0_commit--;
807 break;
808
809 case P0_EXCEP_RET:
810 err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_EXCEPTION_RET);
811 if (!err)
812 {
813 if (pElem->isP0()) // are we on a core that counts ERET as P0?
814 m_elem_res.P0_commit--;
815 }
816 break;
817
818 case P0_FUNC_RET:
819 // func ret is V8M - data trace only - hint that data has been popped off the stack.
820 // at this point nothing to do till the decoder starts handling data trace.
821 if (pElem->isP0())
822 m_elem_res.P0_commit--;
823 break;
824
825 case P0_SRC_ADDR:
826 err = processSourceAddress();
827 m_elem_res.P0_commit--;
828 break;
829
830 case P0_Q:
831 err = processQElement();
832 m_elem_res.P0_commit--;
833 break;
834
835 case P0_TRANS_START:
836 if (m_config->commTransP0())
837 m_elem_res.P0_commit--;
838 case P0_TRANS_COMMIT:
839 case P0_TRANS_FAIL:
840 case P0_TRANS_TRACE_INIT:
841 err = processTransElem(pElem);
842 break;
843 }
844
845 if(bPopElem)
846 m_P0_stack.delete_back(); // remove element from stack;
847 }
848 else
849 {
850 // too few elements for commit operation - decode error.
851 err = handlePacketSeqErr(OCSD_ERR_COMMIT_PKT_OVERRUN, err_idx, "Not enough elements to commit");
852 }
853 }
854
855 // reduce the spec depth by number of comitted elements
856 m_curr_spec_depth -= (num_commit_req-m_elem_res.P0_commit);
857 return err;
858 }
859
returnStackPop()860 ocsd_err_t TrcPktDecodeEtmV4I::returnStackPop()
861 {
862 ocsd_err_t err = OCSD_OK;
863 ocsd_isa nextISA;
864
865 if (m_return_stack.pop_pending())
866 {
867 ocsd_vaddr_t popAddr = m_return_stack.pop(nextISA);
868 if (m_return_stack.overflow())
869 {
870 err = OCSD_ERR_RET_STACK_OVERFLOW;
871 err = handlePacketSeqErr(err, OCSD_BAD_TRC_INDEX, "Trace Return Stack Overflow.");
872 }
873 else
874 {
875 m_instr_info.instr_addr = popAddr;
876 m_instr_info.isa = nextISA;
877 m_need_addr = false;
878 }
879 }
880 return err;
881 }
882
commitElemOnEOT()883 ocsd_err_t TrcPktDecodeEtmV4I::commitElemOnEOT()
884 {
885 ocsd_err_t err = OCSD_OK;
886 TrcStackElem *pElem = 0;
887
888 // nothing outstanding - reset the stack before we add more
889 if (!m_out_elem.numElemToSend())
890 m_out_elem.resetElemStack();
891
892 while((m_P0_stack.size() > 0) && !err)
893 {
894 // scan for outstanding events, TS and CC, that appear before any outstanding
895 // uncommited P0 element.
896 pElem = m_P0_stack.back();
897
898 switch(pElem->getP0Type())
899 {
900 // clear stack and stop
901 case P0_UNKNOWN:
902 case P0_ATOM:
903 case P0_TRC_ON:
904 case P0_EXCEP:
905 case P0_EXCEP_RET:
906 case P0_OVERFLOW:
907 case P0_Q:
908 m_P0_stack.delete_all();
909 break;
910
911 //skip
912 case P0_ADDR:
913 case P0_CTXT:
914 break;
915
916 // trans
917 // P0 trans - clear and stop, otherwise skip
918 case P0_TRANS_START:
919 if (m_config->commTransP0())
920 m_P0_stack.delete_all();
921 break;
922
923 // non-speculative trans fail / commit - could appear at EoT after valid trace
924 // but without a subsequent P0 that would force output.
925 case P0_TRANS_FAIL:
926 case P0_TRANS_COMMIT:
927 if (m_max_spec_depth == 0 || m_curr_spec_depth == 0)
928 err = processTransElem(pElem);
929 break;
930
931 // others - skip non P0
932 case P0_TRANS_TRACE_INIT:
933 break;
934
935 // output
936 case P0_EVENT:
937 case P0_TS:
938 case P0_CC:
939 case P0_TS_CC:
940 err = processTS_CC_EventElem(pElem);
941 break;
942
943 case P0_MARKER:
944 err = processMarkerElem(pElem);
945 break;
946 }
947 m_P0_stack.delete_back();
948 }
949
950 if(!err)
951 {
952 err = m_out_elem.addElemType(m_index_curr_pkt, OCSD_GEN_TRC_ELEM_EO_TRACE);
953 outElem().setUnSyncEOTReason(m_prev_overflow ? UNSYNC_OVERFLOW : UNSYNC_EOT);
954 }
955 return err;
956 }
957
958 // cancel elements. These not output
cancelElements()959 ocsd_err_t TrcPktDecodeEtmV4I::cancelElements()
960 {
961 ocsd_err_t err = OCSD_OK;
962 bool P0StackDone = false; // checked all P0 elements on the stack
963 TrcStackElem *pElem = 0; // stacked element pointer
964 EtmV4P0Stack temp;
965 int num_cancel_req = m_elem_res.P0_cancel;
966
967 while (m_elem_res.P0_cancel)
968 {
969 //search the stack for the newest elements
970 if (!P0StackDone)
971 {
972 if (m_P0_stack.size() == 0)
973 P0StackDone = true;
974 else
975 {
976 // get the newest element
977 pElem = m_P0_stack.front();
978 if (pElem->isP0()) {
979 if (pElem->getP0Type() == P0_ATOM)
980 {
981 TrcStackElemAtom *pAtomElem = (TrcStackElemAtom *)pElem;
982 // atom - cancel N atoms
983 m_elem_res.P0_cancel -= pAtomElem->cancelNewest(m_elem_res.P0_cancel);
984 if (pAtomElem->isEmpty())
985 m_P0_stack.delete_front(); // remove the element
986 }
987 else
988 {
989 m_elem_res.P0_cancel--;
990 m_P0_stack.delete_front(); // remove the element
991 }
992 } else {
993 // not P0, make a keep / remove decision
994 switch (pElem->getP0Type())
995 {
996 // keep these
997 case P0_EVENT:
998 case P0_TS:
999 case P0_CC:
1000 case P0_TS_CC:
1001 case P0_MARKER:
1002 m_P0_stack.pop_front(false);
1003 temp.push_back(pElem);
1004 break;
1005
1006 default:
1007 m_P0_stack.delete_front();
1008 break;
1009 }
1010 }
1011 if (m_P0_stack.size() == 0)
1012 P0StackDone = true;
1013 }
1014 }
1015 // may have some unseen elements
1016 else if (m_unseen_spec_elem)
1017 {
1018 m_unseen_spec_elem--;
1019 m_elem_res.P0_cancel--;
1020 }
1021 // otherwise we have some sort of overrun
1022 else
1023 {
1024 // too few elements for commit operation - decode error.
1025 err = OCSD_ERR_COMMIT_PKT_OVERRUN;
1026 err = handlePacketSeqErr(err, m_index_curr_pkt, "Not enough elements to cancel");
1027 m_elem_res.P0_cancel = 0;
1028 break;
1029 }
1030 }
1031
1032 /* restore any saved elements that are unaffected by cancel. */
1033 if (temp.size())
1034 {
1035 while (temp.size())
1036 {
1037 pElem = temp.back();
1038 m_P0_stack.push_front(pElem);
1039 temp.pop_back(false);
1040 }
1041 }
1042
1043 m_curr_spec_depth -= num_cancel_req - m_elem_res.P0_cancel;
1044 return err;
1045 }
1046
1047 // mispredict an atom
mispredictAtom()1048 ocsd_err_t TrcPktDecodeEtmV4I::mispredictAtom()
1049 {
1050 ocsd_err_t err = OCSD_OK;
1051 bool bFoundAtom = false, bDone = false;
1052 TrcStackElem *pElem = 0;
1053
1054 m_P0_stack.from_front_init(); // init iterator at front.
1055 while (!bDone)
1056 {
1057 pElem = m_P0_stack.from_front_next();
1058 if (pElem)
1059 {
1060 if (pElem->getP0Type() == P0_ATOM)
1061 {
1062 TrcStackElemAtom *pAtomElem = dynamic_cast<TrcStackElemAtom *>(pElem);
1063 if (pAtomElem)
1064 {
1065 pAtomElem->mispredictNewest();
1066 bFoundAtom = true;
1067 }
1068 bDone = true;
1069 }
1070 else if (pElem->getP0Type() == P0_ADDR)
1071 {
1072 // need to disregard any addresses that appear between mispredict and the atom in question
1073 m_P0_stack.erase_curr_from_front();
1074 }
1075 }
1076 else
1077 bDone = true;
1078 }
1079
1080 // if missed atom then either overrun error or mispredict on unseen element
1081 if (!bFoundAtom && !m_unseen_spec_elem)
1082 {
1083 err = OCSD_ERR_COMMIT_PKT_OVERRUN;
1084 err = handlePacketSeqErr(err, m_index_curr_pkt, "Not found mispredict atom");
1085 //LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, m_index_curr_pkt, m_CSID, "Not found mispredict atom"));
1086 }
1087 m_elem_res.mispredict = false;
1088 return err;
1089 }
1090
1091 // discard elements and flush
discardElements()1092 ocsd_err_t TrcPktDecodeEtmV4I::discardElements()
1093 {
1094 ocsd_err_t err = OCSD_OK;
1095 TrcStackElem *pElem = 0; // stacked element pointer
1096
1097 // dump P0, elemnts - output remaining CC / TS
1098 while ((m_P0_stack.size() > 0) && !err)
1099 {
1100 pElem = m_P0_stack.back();
1101 if (pElem->getP0Type() == P0_MARKER)
1102 err = processMarkerElem(pElem);
1103 else
1104 err = processTS_CC_EventElem(pElem);
1105 m_P0_stack.delete_back();
1106 }
1107
1108 // clear all speculation info
1109 clearElemRes();
1110 m_curr_spec_depth = 0;
1111
1112 // set decode state
1113 m_curr_state = NO_SYNC;
1114 m_unsync_eot_info = m_prev_overflow ? UNSYNC_OVERFLOW : UNSYNC_DISCARD;
1115
1116 // unsync so need context & address.
1117 m_need_ctxt = true;
1118 m_need_addr = true;
1119 m_elem_pending_addr = false;
1120 return err;
1121 }
1122
processTS_CC_EventElem(TrcStackElem * pElem)1123 ocsd_err_t TrcPktDecodeEtmV4I::processTS_CC_EventElem(TrcStackElem *pElem)
1124 {
1125 ocsd_err_t err = OCSD_OK;
1126 // ignore ts for ETE if not seen first TS marker on systems that use this.
1127 bool bPermitTS = !m_config->eteHasTSMarker() || m_ete_first_ts_marker;
1128
1129 switch (pElem->getP0Type())
1130 {
1131 case P0_EVENT:
1132 {
1133 TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
1134 if (pParamElem)
1135 err = addElemEvent(pParamElem);
1136 }
1137 break;
1138
1139 case P0_TS:
1140 {
1141 TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
1142 if (pParamElem && bPermitTS)
1143 err = addElemTS(pParamElem, false);
1144 }
1145 break;
1146
1147 case P0_CC:
1148 {
1149 TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
1150 if (pParamElem)
1151 err = addElemCC(pParamElem);
1152 }
1153 break;
1154
1155 case P0_TS_CC:
1156 {
1157 TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
1158 if (pParamElem && bPermitTS)
1159 err = addElemTS(pParamElem, true);
1160 }
1161 break;
1162 }
1163 return err;
1164
1165 }
1166
processMarkerElem(TrcStackElem * pElem)1167 ocsd_err_t TrcPktDecodeEtmV4I::processMarkerElem(TrcStackElem *pElem)
1168 {
1169 ocsd_err_t err = OCSD_OK;
1170 TrcStackElemMarker *pMarkerElem = dynamic_cast<TrcStackElemMarker *>(pElem);
1171
1172 if (m_config->eteHasTSMarker() && (pMarkerElem->getMarker().type == ELEM_MARKER_TS))
1173 m_ete_first_ts_marker = true;
1174
1175 if (!err)
1176 {
1177 err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_SYNC_MARKER);
1178 if (!err)
1179 m_out_elem.getCurrElem().setSyncMarker(pMarkerElem->getMarker());
1180 }
1181 return err;
1182 }
1183
processTransElem(TrcStackElem * pElem)1184 ocsd_err_t TrcPktDecodeEtmV4I::processTransElem(TrcStackElem *pElem)
1185 {
1186 ocsd_err_t err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_MEMTRANS);
1187 if (!err)
1188 {
1189 outElem().setTransactionType((trace_memtrans_t)((int)OCSD_MEM_TRANS_FAIL -
1190 ((int)P0_TRANS_FAIL - (int)pElem->getP0Type())));
1191 }
1192 return err;
1193 }
1194
addElemCC(TrcStackElemParam * pParamElem)1195 ocsd_err_t TrcPktDecodeEtmV4I::addElemCC(TrcStackElemParam *pParamElem)
1196 {
1197 ocsd_err_t err = OCSD_OK;
1198
1199 err = m_out_elem.addElemType(pParamElem->getRootIndex(), OCSD_GEN_TRC_ELEM_CYCLE_COUNT);
1200 if (!err)
1201 outElem().setCycleCount(pParamElem->getParam(0));
1202 return err;
1203 }
1204
addElemTS(TrcStackElemParam * pParamElem,bool withCC)1205 ocsd_err_t TrcPktDecodeEtmV4I::addElemTS(TrcStackElemParam *pParamElem, bool withCC)
1206 {
1207 ocsd_err_t err = OCSD_OK;
1208
1209 err = m_out_elem.addElemType(pParamElem->getRootIndex(), OCSD_GEN_TRC_ELEM_TIMESTAMP);
1210 if (!err)
1211 {
1212 outElem().timestamp = (uint64_t)(pParamElem->getParam(0)) | (((uint64_t)pParamElem->getParam(1)) << 32);
1213 if (withCC)
1214 outElem().setCycleCount(pParamElem->getParam(2));
1215 }
1216 return err;
1217 }
1218
addElemEvent(TrcStackElemParam * pParamElem)1219 ocsd_err_t TrcPktDecodeEtmV4I::addElemEvent(TrcStackElemParam *pParamElem)
1220 {
1221 ocsd_err_t err = OCSD_OK;
1222
1223 err = m_out_elem.addElemType(pParamElem->getRootIndex(), OCSD_GEN_TRC_ELEM_EVENT);
1224 if (!err)
1225 {
1226 outElem().trace_event.ev_type = EVENT_NUMBERED;
1227 outElem().trace_event.ev_number = pParamElem->getParam(0);
1228 }
1229 return err;
1230 }
1231
setElemTraceRange(OcsdTraceElement & elemIn,const instr_range_t & addr_range,const bool executed,ocsd_trc_index_t index)1232 void TrcPktDecodeEtmV4I::setElemTraceRange(OcsdTraceElement &elemIn, const instr_range_t &addr_range,
1233 const bool executed, ocsd_trc_index_t index)
1234 {
1235 setElemTraceRangeInstr(elemIn, addr_range, executed, index, m_instr_info);
1236 }
1237
setElemTraceRangeInstr(OcsdTraceElement & elemIn,const instr_range_t & addr_range,const bool executed,ocsd_trc_index_t index,ocsd_instr_info & instr)1238 void TrcPktDecodeEtmV4I::setElemTraceRangeInstr(OcsdTraceElement &elemIn, const instr_range_t &addr_range,
1239 const bool executed, ocsd_trc_index_t index, ocsd_instr_info &instr)
1240 {
1241 elemIn.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE);
1242 elemIn.setLastInstrInfo(executed, instr.type, instr.sub_type, instr.instr_size);
1243 elemIn.setISA(instr.isa);
1244 elemIn.setLastInstrCond(instr.is_conditional);
1245 elemIn.setAddrRange(addr_range.st_addr, addr_range.en_addr, addr_range.num_instr);
1246 if (executed)
1247 instr.isa = instr.next_isa;
1248 }
1249
processAtom(const ocsd_atm_val atom)1250 ocsd_err_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom)
1251 {
1252 ocsd_err_t err;
1253 TrcStackElem *pElem = m_P0_stack.back(); // get the atom element
1254 WP_res_t WPRes;
1255 instr_range_t addr_range;
1256 bool ETE_ERET = false;
1257
1258 // new element for this processed atom
1259 if ((err = m_out_elem.addElem(pElem->getRootIndex())) != OCSD_OK)
1260 return err;
1261
1262 err = traceInstrToWP(addr_range, WPRes);
1263 if(err != OCSD_OK)
1264 {
1265 if(err == OCSD_ERR_UNSUPPORTED_ISA)
1266 {
1267 m_need_addr = true;
1268 m_need_ctxt = true;
1269 LogError(ocsdError(OCSD_ERR_SEV_WARN,err,pElem->getRootIndex(),m_CSID,"Warning: unsupported instruction set processing atom packet."));
1270 // wait for next context
1271 return OCSD_OK;
1272 }
1273 else
1274 {
1275 err = handlePacketSeqErr(err, pElem->getRootIndex(), "Error processing atom packet.");
1276 //LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,pElem->getRootIndex(),m_CSID,"Error processing atom packet."));
1277 return err;
1278 }
1279 }
1280
1281 if(WPFound(WPRes))
1282 {
1283 // save recorded next instuction address
1284 ocsd_vaddr_t nextAddr = m_instr_info.instr_addr;
1285
1286 // action according to waypoint type and atom value
1287 switch(m_instr_info.type)
1288 {
1289 case OCSD_INSTR_BR:
1290 if (atom == ATOM_E)
1291 {
1292 m_instr_info.instr_addr = m_instr_info.branch_addr;
1293 if (m_instr_info.is_link)
1294 m_return_stack.push(nextAddr, m_instr_info.isa);
1295
1296 }
1297 break;
1298
1299 case OCSD_INSTR_BR_INDIRECT:
1300 if (atom == ATOM_E)
1301 {
1302 m_need_addr = true; // indirect branch taken - need new address.
1303 if (m_instr_info.is_link)
1304 m_return_stack.push(nextAddr,m_instr_info.isa);
1305 m_return_stack.set_pop_pending(); // need to know next packet before we know what is to happen
1306
1307 /* ETE does not have ERET trace packets - however to maintain the illusion if we see an ERET
1308 output a gen elem ERET packet */
1309 if (isETEConfig() && (m_instr_info.sub_type == OCSD_S_INSTR_V8_ERET))
1310 ETE_ERET = true;
1311 }
1312 break;
1313 }
1314 setElemTraceRange(outElem(), addr_range, (atom == ATOM_E), pElem->getRootIndex());
1315
1316 if (ETE_ERET)
1317 {
1318 err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_EXCEPTION_RET);
1319 if (err)
1320 return err;
1321 }
1322 }
1323 else
1324 {
1325 // no waypoint - likely inaccessible memory range.
1326 m_need_addr = true; // need an address update
1327
1328 if(addr_range.st_addr != addr_range.en_addr)
1329 {
1330 // some trace before we were out of memory access range
1331 setElemTraceRange(outElem(), addr_range, true, pElem->getRootIndex());
1332
1333 // another element for the nacc...
1334 if (WPNacc(WPRes))
1335 err = m_out_elem.addElem(pElem->getRootIndex());
1336 }
1337
1338 if(WPNacc(WPRes) && !err)
1339 {
1340 outElem().setType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
1341 outElem().st_addr = m_instr_info.instr_addr;
1342 }
1343 }
1344 return err;
1345 }
1346
1347 // Exception processor
processException()1348 ocsd_err_t TrcPktDecodeEtmV4I::processException()
1349 {
1350 ocsd_err_t err;
1351 TrcStackElem *pElem = 0;
1352 TrcStackElemExcept *pExceptElem = 0;
1353 TrcStackElemAddr *pAddressElem = 0;
1354 TrcStackElemCtxt *pCtxtElem = 0;
1355 bool branch_target = false; // exception address implies prior branch target address
1356 ocsd_vaddr_t excep_ret_addr = 0;
1357 ocsd_trc_index_t excep_pkt_index;
1358 WP_res_t WPRes = WP_NOT_FOUND;
1359 bool ETE_resetPkt = false;
1360
1361 // grab the exception element off the stack
1362 pExceptElem = dynamic_cast<TrcStackElemExcept *>(m_P0_stack.back()); // get the exception element
1363 excep_pkt_index = pExceptElem->getRootIndex();
1364 branch_target = pExceptElem->getPrevSame();
1365 if (pExceptElem->getRootPkt() == ETE_PKT_I_PE_RESET)
1366 ETE_resetPkt = true;
1367 m_P0_stack.pop_back(); // remove the exception element
1368
1369 // ETE reset has no follow up address, the rest of the exceptions do....
1370 if (!ETE_resetPkt)
1371 {
1372 pElem = m_P0_stack.back(); // look at next element.
1373 if (pElem->getP0Type() == P0_CTXT)
1374 {
1375 pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem);
1376 m_P0_stack.pop_back(); // remove the context element
1377 pElem = m_P0_stack.back(); // next one should be an address element
1378 }
1379
1380 if (pElem->getP0Type() != P0_ADDR)
1381 {
1382 // no following address element - indicate processing error.
1383
1384 err = handlePacketSeqErr(OCSD_ERR_BAD_PACKET_SEQ, m_index_curr_pkt, "Address missing in exception packet.");
1385 //LogError(ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_BAD_PACKET_SEQ, excep_pkt_index, m_CSID, "Address missing in exception packet."));
1386 return err;
1387 }
1388 else
1389 {
1390 // extract address
1391 pAddressElem = static_cast<TrcStackElemAddr *>(pElem);
1392 excep_ret_addr = pAddressElem->getAddr().val;
1393
1394 // see if there is an address + optional context element implied
1395 // prior to the exception.
1396 if (branch_target)
1397 {
1398 // this was a branch target address - update current setting
1399 bool b64bit = m_instr_info.isa == ocsd_isa_aarch64;
1400 if (pCtxtElem) {
1401 b64bit = pCtxtElem->getContext().SF;
1402 }
1403
1404 // as the exception address was also a branch target address then update the
1405 // current maintained address value. This also means that there is no range to
1406 // output before the exception packet.
1407 m_instr_info.instr_addr = excep_ret_addr;
1408 m_instr_info.isa = (pAddressElem->getAddr().isa == 0) ?
1409 (b64bit ? ocsd_isa_aarch64 : ocsd_isa_arm) : ocsd_isa_thumb2;
1410 m_need_addr = false;
1411 }
1412 }
1413 }
1414
1415 // need to output something - set up an element
1416 if ((err = m_out_elem.addElem(excep_pkt_index)))
1417 return err;
1418
1419 // output a context element if present
1420 if (pCtxtElem)
1421 {
1422 updateContext(pCtxtElem, outElem());
1423
1424 // used the element - need another for later stages
1425 if ((err = m_out_elem.addElem(excep_pkt_index)))
1426 return err;
1427 }
1428
1429 if (!ETE_resetPkt)
1430 {
1431 // if the preferred return address is not the end of the last output range...
1432 if (m_instr_info.instr_addr != excep_ret_addr)
1433 {
1434 bool range_out = false;
1435 instr_range_t addr_range;
1436
1437 // look for match to return address.
1438 err = traceInstrToWP(addr_range, WPRes, true, excep_ret_addr);
1439
1440 if (err != OCSD_OK)
1441 {
1442 if (err == OCSD_ERR_UNSUPPORTED_ISA)
1443 {
1444 m_need_addr = true;
1445 m_need_ctxt = true;
1446 LogError(ocsdError(OCSD_ERR_SEV_WARN, err, excep_pkt_index, m_CSID, "Warning: unsupported instruction set processing exception packet."));
1447 }
1448 else
1449 {
1450 LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, excep_pkt_index, m_CSID, "Error processing exception packet."));
1451 }
1452 return err;
1453 }
1454
1455 if (WPFound(WPRes))
1456 {
1457 // waypoint address found - output range
1458 setElemTraceRange(outElem(), addr_range, true, excep_pkt_index);
1459 range_out = true;
1460 }
1461 else
1462 {
1463 // no waypoint - likely inaccessible memory range.
1464 m_need_addr = true; // need an address update
1465
1466 if (addr_range.st_addr != addr_range.en_addr)
1467 {
1468 // some trace before we were out of memory access range
1469 setElemTraceRange(outElem(), addr_range, true, excep_pkt_index);
1470 range_out = true;
1471 }
1472 }
1473
1474 // used the element need another for NACC or EXCEP.
1475 if (range_out)
1476 {
1477 if ((err = m_out_elem.addElem(excep_pkt_index)))
1478 return err;
1479 }
1480 }
1481
1482 // watchpoint walk resulted in inaccessible memory call...
1483 if (WPNacc(WPRes))
1484 {
1485
1486 outElem().setType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
1487 outElem().st_addr = m_instr_info.instr_addr;
1488
1489 // used the element - need another for the final exception packet.
1490 if ((err = m_out_elem.addElem(excep_pkt_index)))
1491 return err;
1492 }
1493 }
1494
1495 // output exception element.
1496 outElem().setType(OCSD_GEN_TRC_ELEM_EXCEPTION);
1497
1498 // add end address as preferred return address to end addr in element
1499 outElem().en_addr = excep_ret_addr;
1500 outElem().excep_ret_addr = 1;
1501 outElem().excep_ret_addr_br_tgt = branch_target;
1502 outElem().exception_number = pExceptElem->getExcepNum();
1503
1504 m_P0_stack.delete_popped(); // clear the used elements from the stack
1505 return err;
1506 }
1507
processQElement()1508 ocsd_err_t TrcPktDecodeEtmV4I::processQElement()
1509 {
1510 ocsd_err_t err = OCSD_OK;
1511 TrcStackQElem *pQElem;
1512 etmv4_addr_val_t QAddr; // address where trace restarts
1513 int iCount = 0;
1514
1515 pQElem = dynamic_cast<TrcStackQElem *>(m_P0_stack.back()); // get the exception element
1516 m_P0_stack.pop_back(); // remove the Q element.
1517
1518 if (!pQElem->hasAddr()) // no address - it must be next on the stack....
1519 {
1520 TrcStackElemAddr *pAddressElem = 0;
1521 TrcStackElemCtxt *pCtxtElem = 0;
1522 TrcStackElem *pElem = 0;
1523
1524 pElem = m_P0_stack.back(); // look at next element.
1525 if (pElem->getP0Type() == P0_CTXT)
1526 {
1527 pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem);
1528 m_P0_stack.pop_back(); // remove the context element
1529 pElem = m_P0_stack.back(); // next one should be an address element
1530 }
1531
1532 if (pElem->getP0Type() != P0_ADDR)
1533 {
1534 // no following address element - indicate processing error.
1535 err = OCSD_ERR_BAD_PACKET_SEQ;
1536 LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pQElem->getRootIndex(), m_CSID, "Address missing in Q packet."));
1537 m_P0_stack.delete_popped();
1538 return err;
1539 }
1540 pAddressElem = dynamic_cast<TrcStackElemAddr *>(pElem);
1541 QAddr = pAddressElem->getAddr();
1542 m_P0_stack.pop_back(); // remove the address element
1543 m_P0_stack.delete_popped(); // clear used elements
1544
1545 // return the context element for processing next time.
1546 if (pCtxtElem)
1547 {
1548 // need a new copy at the back - old one will be deleted as popped.
1549 m_P0_stack.createContextElem(pCtxtElem->getRootPkt(), pCtxtElem->getRootIndex(), pCtxtElem->getContext(),true);
1550 }
1551 }
1552 else
1553 QAddr = pQElem->getAddr();
1554
1555 // process the Q element with address.
1556 iCount = pQElem->getInstrCount();
1557
1558 bool isBranch = false;
1559
1560 // need to output something - set up an element
1561 if ((err = m_out_elem.addElem(pQElem->getRootIndex())))
1562 return err;
1563
1564 instr_range_t addr_range;
1565 addr_range.st_addr = addr_range.en_addr = m_instr_info.instr_addr;
1566 addr_range.num_instr = 0;
1567
1568 // walk iCount instructions
1569 for (int i = 0; i < iCount; i++)
1570 {
1571 uint32_t opcode;
1572 uint32_t bytesReq = 4;
1573
1574 err = accessMemory(m_instr_info.instr_addr, getCurrMemSpace(), &bytesReq, (uint8_t *)&opcode);
1575 if (err != OCSD_OK) break;
1576
1577 if (bytesReq == 4) // got data back
1578 {
1579 m_instr_info.opcode = opcode;
1580 err = instrDecode(&m_instr_info);
1581 if (err != OCSD_OK) break;
1582
1583 // increment address - may be adjusted by direct branch value later
1584 m_instr_info.instr_addr += m_instr_info.instr_size;
1585 addr_range.num_instr++;
1586
1587 isBranch = (m_instr_info.type == OCSD_INSTR_BR) ||
1588 (m_instr_info.type == OCSD_INSTR_BR_INDIRECT);
1589
1590 // on a branch no way of knowing if taken - bail out
1591 if (isBranch)
1592 break;
1593 }
1594 else
1595 break; // missing memory
1596
1597 }
1598
1599 if (err == OCSD_OK)
1600 {
1601 bool inCompleteRange = true;
1602 if (iCount && (addr_range.num_instr == (unsigned)iCount))
1603 {
1604 if ((m_instr_info.instr_addr == QAddr.val) || // complete range
1605 (isBranch)) // or ends on branch - only way we know if branch taken.
1606 {
1607 // output a range and continue
1608 inCompleteRange = false;
1609 // update the range decoded address in the output packet.
1610 addr_range.en_addr = m_instr_info.instr_addr;
1611 setElemTraceRange(outElem(), addr_range, true, pQElem->getRootIndex());
1612 }
1613 }
1614
1615 if (inCompleteRange)
1616 {
1617 // unknown instructions executed.
1618 addr_range.en_addr = QAddr.val;
1619 addr_range.num_instr = iCount;
1620
1621 outElem().setType(OCSD_GEN_TRC_ELEM_I_RANGE_NOPATH);
1622 outElem().setAddrRange(addr_range.st_addr, addr_range.en_addr, addr_range.num_instr);
1623 outElem().setISA(calcISA(m_is_64bit, QAddr.isa));
1624 }
1625
1626 // after the Q element, tracing resumes at the address supplied
1627 SetInstrInfoInAddrISA(QAddr.val, QAddr.isa);
1628 m_need_addr = false;
1629 }
1630 else
1631 {
1632 // output error and halt decode.
1633 LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pQElem->getRootIndex(), m_CSID, "Error processing Q packet"));
1634 }
1635 m_P0_stack.delete_popped();
1636 return err;
1637 }
1638
processSourceAddress()1639 ocsd_err_t TrcPktDecodeEtmV4I::processSourceAddress()
1640 {
1641 ocsd_err_t err = OCSD_OK;
1642 TrcStackElemAddr *pElem = dynamic_cast<TrcStackElemAddr *>(m_P0_stack.back()); // get the address element
1643 etmv4_addr_val_t srcAddr = pElem->getAddr();
1644 uint32_t opcode, bytesReq = 4;
1645 ocsd_vaddr_t currAddr = m_instr_info.instr_addr; // get the latest decoded address.
1646 instr_range_t out_range;
1647 bool bSplitRangeOnN = getComponentOpMode() & ETE_OPFLG_PKTDEC_SRCADDR_N_ATOMS ? true : false;
1648
1649 // check we can read instruction @ source address
1650 err = accessMemory(srcAddr.val, getCurrMemSpace(), &bytesReq, (uint8_t *)&opcode);
1651 if (err != OCSD_OK)
1652 {
1653 LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pElem->getRootIndex(), m_CSID, "Mem access error processing source address packet."));
1654 return err;
1655 }
1656
1657 if (bytesReq != 4)
1658 {
1659 // can't access - no bytes returned - output nacc.
1660 err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_ADDR_NACC);
1661 outElem().setAddrStart(srcAddr.val);
1662 return err;
1663 }
1664
1665 // analyze opcode @ source address.
1666 m_instr_info.opcode = opcode;
1667 m_instr_info.instr_addr = srcAddr.val;
1668 err = instrDecode(&m_instr_info);
1669 if (err != OCSD_OK)
1670 {
1671 LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pElem->getRootIndex(), m_CSID, "Instruction decode error processing source address packet."));
1672 return err;
1673 }
1674 m_instr_info.instr_addr += m_instr_info.instr_size;
1675
1676 // initial instruction count for the range.
1677 out_range.num_instr = 1;
1678
1679 // calculate range traced...
1680 if (m_need_addr || (currAddr > srcAddr.val))
1681 {
1682 // we were waiting for a target address, or missing trace
1683 // that indicates how we got to the source address.
1684 m_need_addr = false;
1685 out_range.st_addr = srcAddr.val;
1686 }
1687 else
1688 out_range.st_addr = currAddr;
1689 out_range.en_addr = m_instr_info.instr_addr;
1690
1691 // count instructions
1692 if (out_range.en_addr - out_range.st_addr > m_instr_info.instr_size)
1693 {
1694 if ((m_instr_info.isa != ocsd_isa_thumb2) && !bSplitRangeOnN)
1695 {
1696 // all 4 byte instructions - just calculate...
1697 out_range.num_instr = (uint32_t)(out_range.en_addr - out_range.st_addr) / 4;
1698 }
1699 else
1700 {
1701 // need to count T32 - 2 or 4 byte instructions or we are spotting N atoms
1702 ocsd_instr_info instr; // going back to start of range so make a copy of info.
1703 bool bMemAccErr = false;
1704
1705 instr.instr_addr = out_range.st_addr;
1706 instr.isa = m_instr_info.isa;
1707 instr.pe_type = m_instr_info.pe_type;
1708 instr.dsb_dmb_waypoints = m_instr_info.dsb_dmb_waypoints;
1709 instr.wfi_wfe_branch = m_instr_info.wfi_wfe_branch;
1710 out_range.num_instr = 0;
1711
1712 while ((instr.instr_addr < out_range.en_addr) && !bMemAccErr)
1713 {
1714 bytesReq = 4;
1715 err = accessMemory(instr.instr_addr, getCurrMemSpace(), &bytesReq, (uint8_t *)&opcode);
1716 if (err != OCSD_OK)
1717 {
1718 LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pElem->getRootIndex(), m_CSID, "Mem access error processing source address packet."));
1719 return err;
1720 }
1721
1722 if (bytesReq == 4)
1723 {
1724 instr.opcode = opcode;
1725 err = instrDecode(&instr);
1726 if (err != OCSD_OK)
1727 {
1728 LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pElem->getRootIndex(), m_CSID, "Instruction decode error processing source address packet."));
1729 return err;
1730 }
1731
1732 instr.instr_addr += instr.instr_size;
1733 out_range.num_instr++;
1734
1735 /* if we are doing N atom ranges ...*/
1736 if (bSplitRangeOnN && (instr.instr_addr < out_range.en_addr))
1737 {
1738 if (instr.type != OCSD_INSTR_OTHER)
1739 {
1740 instr_range_t mid_range = out_range;
1741 mid_range.en_addr = instr.instr_addr;
1742
1743 err = m_out_elem.addElem(pElem->getRootIndex());
1744 if (err)
1745 return err;
1746 setElemTraceRangeInstr(outElem(), mid_range, false, pElem->getRootIndex(), instr);
1747
1748 out_range.st_addr = mid_range.en_addr;
1749 out_range.num_instr = 0;
1750 }
1751 }
1752 }
1753 else
1754 {
1755 // something inaccessible between last and current...
1756 bMemAccErr = true;
1757
1758 err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_ADDR_NACC);
1759 if (err)
1760 return err;
1761 outElem().setAddrStart(srcAddr.val);
1762
1763 // force range to the one instruction
1764 out_range.num_instr = 1;
1765 out_range.st_addr = srcAddr.val;
1766 out_range.en_addr = m_instr_info.instr_addr; // instr after the decoded instruction @ srcAddr.
1767 }
1768 }
1769 }
1770 }
1771
1772 // got to the source address - output trace range, and instruction as E atom.
1773 switch (m_instr_info.type)
1774 {
1775 case OCSD_INSTR_BR:
1776 if (m_instr_info.is_link)
1777 m_return_stack.push(m_instr_info.instr_addr, m_instr_info.isa);
1778 m_instr_info.instr_addr = m_instr_info.branch_addr;
1779 break;
1780
1781 case OCSD_INSTR_BR_INDIRECT:
1782 m_need_addr = true; // indirect branch taken - need new address.
1783 if (m_instr_info.is_link)
1784 m_return_stack.push(m_instr_info.instr_addr, m_instr_info.isa);
1785 m_return_stack.set_pop_pending(); // need to know next packet before we know what is to happen
1786 break;
1787 }
1788 m_instr_info.isa = m_instr_info.next_isa;
1789
1790 // set the trace range element.
1791 m_out_elem.addElem(pElem->getRootIndex());
1792 setElemTraceRange(outElem(), out_range, true, pElem->getRootIndex());
1793 return err;
1794 }
1795
SetInstrInfoInAddrISA(const ocsd_vaddr_t addr_val,const uint8_t isa)1796 void TrcPktDecodeEtmV4I::SetInstrInfoInAddrISA(const ocsd_vaddr_t addr_val, const uint8_t isa)
1797 {
1798 m_instr_info.instr_addr = addr_val;
1799 m_instr_info.isa = calcISA(m_is_64bit, isa);
1800 }
1801
1802 // 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)1803 ocsd_err_t TrcPktDecodeEtmV4I::traceInstrToWP(instr_range_t &range, WP_res_t &WPRes, const bool traceToAddrNext /*= false*/, const ocsd_vaddr_t nextAddrMatch /*= 0*/)
1804 {
1805 uint32_t opcode;
1806 uint32_t bytesReq;
1807 ocsd_err_t err = OCSD_OK;
1808
1809 range.st_addr = range.en_addr = m_instr_info.instr_addr;
1810 range.num_instr = 0;
1811
1812 WPRes = WP_NOT_FOUND;
1813
1814 while(WPRes == WP_NOT_FOUND)
1815 {
1816 // start off by reading next opcode;
1817 bytesReq = 4;
1818 err = accessMemory(m_instr_info.instr_addr, getCurrMemSpace(),&bytesReq,(uint8_t *)&opcode);
1819 if(err != OCSD_OK) break;
1820
1821 if(bytesReq == 4) // got data back
1822 {
1823 m_instr_info.opcode = opcode;
1824 err = instrDecode(&m_instr_info);
1825 if(err != OCSD_OK) break;
1826
1827 // increment address - may be adjusted by direct branch value later
1828 m_instr_info.instr_addr += m_instr_info.instr_size;
1829 range.num_instr++;
1830
1831 // either walking to match the next instruction address or a real watchpoint
1832 if (traceToAddrNext)
1833 {
1834 if (m_instr_info.instr_addr == nextAddrMatch)
1835 WPRes = WP_FOUND;
1836 }
1837 else if (m_instr_info.type != OCSD_INSTR_OTHER)
1838 WPRes = WP_FOUND;
1839 }
1840 else
1841 {
1842 // not enough memory accessible.
1843 WPRes = WP_NACC;
1844 }
1845 }
1846 // update the range decoded address in the output packet.
1847 range.en_addr = m_instr_info.instr_addr;
1848 return err;
1849 }
1850
updateContext(TrcStackElemCtxt * pCtxtElem,OcsdTraceElement & elem)1851 void TrcPktDecodeEtmV4I::updateContext(TrcStackElemCtxt *pCtxtElem, OcsdTraceElement &elem)
1852 {
1853 etmv4_context_t ctxt = pCtxtElem->getContext();
1854
1855 elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT);
1856
1857 // map to output element and local saved state.
1858 m_is_64bit = (ctxt.SF != 0);
1859 elem.context.bits64 = ctxt.SF;
1860 m_is_secure = (ctxt.NS == 0);
1861 elem.context.security_level = ctxt.NS ? ocsd_sec_nonsecure : ocsd_sec_secure;
1862 elem.context.exception_level = (ocsd_ex_level)ctxt.EL;
1863 elem.context.el_valid = 1;
1864 if(ctxt.updated_c)
1865 {
1866 elem.context.ctxt_id_valid = 1;
1867 m_context_id = elem.context.context_id = ctxt.ctxtID;
1868 }
1869 if(ctxt.updated_v)
1870 {
1871 elem.context.vmid_valid = 1;
1872 m_vmid_id = elem.context.vmid = ctxt.VMID;
1873 }
1874
1875 // need to update ISA in case context follows address.
1876 elem.isa = m_instr_info.isa = calcISA(m_is_64bit, pCtxtElem->getIS());
1877 m_need_ctxt = false;
1878 }
1879
handleBadPacket(const char * reason,ocsd_trc_index_t index)1880 ocsd_err_t TrcPktDecodeEtmV4I::handleBadPacket(const char *reason, ocsd_trc_index_t index /* = OCSD_BAD_TRC_INDEX */)
1881 {
1882 ocsd_err_severity_t sev = OCSD_ERR_SEV_WARN;
1883 if (getComponentOpMode() & OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS)
1884 sev = OCSD_ERR_SEV_ERROR;
1885
1886 return handlePacketErr(OCSD_ERR_BAD_DECODE_PKT, sev, index, reason);
1887 }
1888
handlePacketSeqErr(ocsd_err_t err,ocsd_trc_index_t index,const char * reason)1889 ocsd_err_t TrcPktDecodeEtmV4I::handlePacketSeqErr(ocsd_err_t err, ocsd_trc_index_t index, const char *reason)
1890 {
1891 return handlePacketErr(err, OCSD_ERR_SEV_ERROR, index, reason);
1892 }
1893
handlePacketErr(ocsd_err_t err,ocsd_err_severity_t sev,ocsd_trc_index_t index,const char * reason)1894 ocsd_err_t TrcPktDecodeEtmV4I::handlePacketErr(ocsd_err_t err, ocsd_err_severity_t sev, ocsd_trc_index_t index, const char *reason)
1895 {
1896 bool resetOnBadPackets = true;
1897
1898 if(getComponentOpMode() & OCSD_OPFLG_PKTDEC_HALT_BAD_PKTS)
1899 resetOnBadPackets = false;
1900
1901 LogError(ocsdError(sev, err, index, getCoreSightTraceID(), reason));
1902
1903 if (resetOnBadPackets)
1904 {
1905 // switch to unsync - clear decode state
1906 resetDecoder();
1907 m_curr_state = NO_SYNC;
1908 m_unsync_eot_info = UNSYNC_BAD_PACKET;
1909 err = OCSD_OK;
1910 }
1911 return err;
1912
1913 }
1914
1915
getCurrMemSpace()1916 inline ocsd_mem_space_acc_t TrcPktDecodeEtmV4I::getCurrMemSpace()
1917 {
1918 static ocsd_mem_space_acc_t SMemSpace[] = {
1919 OCSD_MEM_SPACE_EL1S,
1920 OCSD_MEM_SPACE_EL1S,
1921 OCSD_MEM_SPACE_EL2S,
1922 OCSD_MEM_SPACE_EL3
1923 };
1924
1925 static ocsd_mem_space_acc_t NSMemSpace[] = {
1926 OCSD_MEM_SPACE_EL1N,
1927 OCSD_MEM_SPACE_EL1N,
1928 OCSD_MEM_SPACE_EL2,
1929 OCSD_MEM_SPACE_EL3
1930 };
1931
1932 /* if no valid EL value - just use S/NS */
1933 if (!outElem().context.el_valid)
1934 return m_is_secure ? OCSD_MEM_SPACE_S : OCSD_MEM_SPACE_N;
1935
1936 /* mem space according to EL + S/NS */
1937 int el = (int)(outElem().context.exception_level) & 0x3;
1938 return m_is_secure ? SMemSpace[el] : NSMemSpace[el];
1939 }
1940 /* End of File trc_pkt_decode_etmv4i.cpp */
1941