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