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