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