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