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