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 44 TrcPktDecodeEtmV4I::TrcPktDecodeEtmV4I() 45 : TrcPktDecodeBase(DCD_NAME) 46 { 47 initDecoder(); 48 } 49 50 TrcPktDecodeEtmV4I::TrcPktDecodeEtmV4I(int instIDNum) 51 : TrcPktDecodeBase(DCD_NAME,instIDNum) 52 { 53 initDecoder(); 54 } 55 56 TrcPktDecodeEtmV4I::~TrcPktDecodeEtmV4I() 57 { 58 } 59 60 /*********************** implementation packet decoding interface */ 61 62 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processPacket() 63 { 64 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 65 ocsd_err_t err = OCSD_OK; 66 bool bPktDone = false; 67 68 while(!bPktDone) 69 { 70 switch (m_curr_state) 71 { 72 case NO_SYNC: 73 // output the initial not synced packet to the sink 74 err = m_out_elem.resetElemStack(); 75 if (!err) 76 err = m_out_elem.addElemType(m_index_curr_pkt, OCSD_GEN_TRC_ELEM_NO_SYNC); 77 if (!err) 78 { 79 outElem().setUnSyncEOTReason(m_unsync_eot_info); 80 resp = m_out_elem.sendElements(); 81 m_curr_state = WAIT_SYNC; 82 } 83 else 84 resp = OCSD_RESP_FATAL_SYS_ERR; 85 86 // fall through to check if the current packet is the async we are waiting for. 87 break; 88 89 case WAIT_SYNC: 90 if(m_curr_packet_in->getType() == ETM4_PKT_I_ASYNC) 91 m_curr_state = WAIT_TINFO; 92 bPktDone = true; 93 break; 94 95 case WAIT_TINFO: 96 m_need_ctxt = true; 97 m_need_addr = true; 98 if(m_curr_packet_in->getType() == ETM4_PKT_I_TRACE_INFO) 99 { 100 doTraceInfoPacket(); 101 m_curr_state = DECODE_PKTS; 102 m_return_stack.flush(); 103 } 104 bPktDone = true; 105 break; 106 107 case DECODE_PKTS: 108 // this may change the state to RESOLVE_ELEM if required; 109 err = decodePacket(); 110 if (err) 111 { 112 #ifdef OCSD_WARN_UNSUPPORTED 113 if (err == OCSD_ERR_UNSUPP_DECODE_PKT) 114 resp = OCSD_RESP_WARN_CONT; 115 else 116 #else 117 resp = OCSD_RESP_FATAL_INVALID_DATA; 118 #endif 119 120 bPktDone = true; 121 } 122 else if (m_curr_state != RESOLVE_ELEM) 123 bPktDone = true; 124 break; 125 126 case RESOLVE_ELEM: 127 // this will change the state to DECODE_PKTS once required elem resolved & 128 // needed generic packets output 129 resp = resolveElements(); 130 if ((m_curr_state == DECODE_PKTS) || (!OCSD_DATA_RESP_IS_CONT(resp))) 131 bPktDone = true; 132 break; 133 } 134 } 135 return resp; 136 } 137 138 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::onEOT() 139 { 140 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 141 ocsd_err_t err; 142 if ((err = commitElemOnEOT()) != OCSD_OK) 143 { 144 resp = OCSD_RESP_FATAL_INVALID_DATA; 145 LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, "Error flushing element stack at end of trace data.")); 146 } 147 else 148 resp = m_out_elem.sendElements(); 149 return resp; 150 } 151 152 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::onReset() 153 { 154 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 155 m_unsync_eot_info = UNSYNC_RESET_DECODER; 156 resetDecoder(); 157 return resp; 158 } 159 160 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::onFlush() 161 { 162 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 163 164 if (m_curr_state == RESOLVE_ELEM) 165 resp = resolveElements(); 166 else 167 resp = m_out_elem.sendElements(); 168 return resp; 169 } 170 171 ocsd_err_t TrcPktDecodeEtmV4I::onProtocolConfig() 172 { 173 ocsd_err_t err = OCSD_OK; 174 175 // set some static config elements 176 m_CSID = m_config->getTraceID(); 177 m_max_spec_depth = m_config->MaxSpecDepth(); 178 179 // elements associated with data trace 180 #ifdef DATA_TRACE_SUPPORTED 181 m_p0_key_max = m_config->P0_Key_Max(); 182 m_cond_key_max_incr = m_config->CondKeyMaxIncr(); 183 #endif 184 185 m_out_elem.initCSID(m_CSID); 186 187 // set up static trace instruction decode elements 188 m_instr_info.dsb_dmb_waypoints = 0; 189 m_instr_info.wfi_wfe_branch = m_config->wfiwfeBranch() ? 1 : 0; 190 m_instr_info.pe_type.arch = m_config->archVersion(); 191 m_instr_info.pe_type.profile = m_config->coreProfile(); 192 193 m_IASize64 = (m_config->iaSizeMax() == 64); 194 195 if (m_config->enabledRetStack()) 196 { 197 m_return_stack.set_active(true); 198 #ifdef TRC_RET_STACK_DEBUG 199 m_return_stack.set_dbg_logger(this); 200 #endif 201 } 202 203 // check config compatible with current decoder support level. 204 // at present no data trace, no spec depth, no return stack, no QE 205 // Remove these checks as support is added. 206 if(m_config->enabledDataTrace()) 207 { 208 err = OCSD_ERR_HW_CFG_UNSUPP; 209 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : Data trace elements not supported")); 210 } 211 else if(m_config->enabledLSP0Trace()) 212 { 213 err = OCSD_ERR_HW_CFG_UNSUPP; 214 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : LSP0 elements not supported.")); 215 } 216 else if(m_config->enabledCondITrace() != EtmV4Config::COND_TR_DIS) 217 { 218 err = OCSD_ERR_HW_CFG_UNSUPP; 219 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : Trace on conditional non-branch elements not supported.")); 220 } 221 return err; 222 } 223 224 /************* local decode methods */ 225 void TrcPktDecodeEtmV4I::initDecoder() 226 { 227 // set the operational modes supported. 228 m_supported_op_flags = ETMV4_SUPPORTED_DECODE_OP_FLAGS; 229 230 /* init elements that get set by config */ 231 m_max_spec_depth = 0; 232 m_CSID = 0; 233 m_IASize64 = false; 234 235 // elements associated with data trace 236 #ifdef DATA_TRACE_SUPPORTED 237 m_p0_key_max = 0; 238 m_cond_key_max_incr = 0; 239 #endif 240 241 // reset decoder state to unsynced 242 m_unsync_eot_info = UNSYNC_INIT_DECODER; 243 resetDecoder(); 244 } 245 246 void TrcPktDecodeEtmV4I::resetDecoder() 247 { 248 m_curr_state = NO_SYNC; 249 m_timestamp = 0; 250 m_context_id = 0; 251 m_vmid_id = 0; 252 m_is_secure = true; 253 m_is_64bit = false; 254 m_cc_threshold = 0; 255 m_curr_spec_depth = 0; 256 m_need_ctxt = true; 257 m_need_addr = true; 258 m_elem_pending_addr = false; 259 m_prev_overflow = false; 260 m_P0_stack.delete_all(); 261 m_out_elem.resetElemStack(); 262 m_last_IS = 0; 263 clearElemRes(); 264 265 // elements associated with data trace 266 #ifdef DATA_TRACE_SUPPORTED 267 m_p0_key = 0; 268 m_cond_c_key = 0; 269 m_cond_r_key = 0; 270 #endif 271 } 272 273 void TrcPktDecodeEtmV4I::onFirstInitOK() 274 { 275 // once init, set the output element interface to the out elem list. 276 m_out_elem.initSendIf(this->getTraceElemOutAttachPt()); 277 } 278 279 // Changes a packet into stack of trace elements - these will be resolved and output later 280 ocsd_err_t TrcPktDecodeEtmV4I::decodePacket() 281 { 282 ocsd_err_t err = OCSD_OK; 283 bool bAllocErr = false; 284 bool is_addr = false; 285 286 switch(m_curr_packet_in->getType()) 287 { 288 case ETM4_PKT_I_ASYNC: // nothing to do with this packet. 289 case ETM4_PKT_I_IGNORE: // or this one. 290 break; 291 292 case ETM4_PKT_I_TRACE_INFO: 293 // skip subsequent TInfo packets. 294 m_return_stack.flush(); 295 break; 296 297 case ETM4_PKT_I_TRACE_ON: 298 { 299 if (m_P0_stack.createParamElemNoParam(P0_TRC_ON, false, m_curr_packet_in->getType(), m_index_curr_pkt) == 0) 300 bAllocErr = true; 301 } 302 break; 303 304 case ETM4_PKT_I_ATOM_F1: 305 case ETM4_PKT_I_ATOM_F2: 306 case ETM4_PKT_I_ATOM_F3: 307 case ETM4_PKT_I_ATOM_F4: 308 case ETM4_PKT_I_ATOM_F5: 309 case ETM4_PKT_I_ATOM_F6: 310 { 311 if (m_P0_stack.createAtomElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getAtom()) == 0) 312 bAllocErr = true; 313 else 314 m_curr_spec_depth += m_curr_packet_in->getAtom().num; 315 } 316 break; 317 318 case ETM4_PKT_I_CTXT: 319 { 320 if (m_P0_stack.createContextElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getContext(), m_last_IS) == 0) 321 bAllocErr = true; 322 } 323 break; 324 325 case ETM4_PKT_I_ADDR_MATCH: 326 { 327 etmv4_addr_val_t addr; 328 329 addr.val = m_curr_packet_in->getAddrVal(); 330 addr.isa = m_last_IS = m_curr_packet_in->getAddrIS(); 331 332 if (m_P0_stack.createAddrElem(m_curr_packet_in->getType(), m_index_curr_pkt, addr) == 0) 333 bAllocErr = true; 334 is_addr = true; 335 } 336 break; 337 338 case ETM4_PKT_I_ADDR_CTXT_L_64IS0: 339 case ETM4_PKT_I_ADDR_CTXT_L_64IS1: 340 case ETM4_PKT_I_ADDR_CTXT_L_32IS0: 341 case ETM4_PKT_I_ADDR_CTXT_L_32IS1: 342 { 343 m_last_IS = m_curr_packet_in->getAddrIS(); 344 if (m_P0_stack.createContextElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getContext(), m_last_IS) == 0) 345 bAllocErr = true; 346 } 347 case ETM4_PKT_I_ADDR_L_32IS0: 348 case ETM4_PKT_I_ADDR_L_32IS1: 349 case ETM4_PKT_I_ADDR_L_64IS0: 350 case ETM4_PKT_I_ADDR_L_64IS1: 351 case ETM4_PKT_I_ADDR_S_IS0: 352 case ETM4_PKT_I_ADDR_S_IS1: 353 { 354 etmv4_addr_val_t addr; 355 356 addr.val = m_curr_packet_in->getAddrVal(); 357 addr.isa = m_last_IS = m_curr_packet_in->getAddrIS(); 358 359 if (m_P0_stack.createAddrElem(m_curr_packet_in->getType(), m_index_curr_pkt, addr) == 0) 360 bAllocErr = true; 361 is_addr = true; 362 } 363 break; 364 365 // Exceptions 366 case ETM4_PKT_I_EXCEPT: 367 { 368 if (m_P0_stack.createExceptElem(m_curr_packet_in->getType(), m_index_curr_pkt, 369 (m_curr_packet_in->exception_info.addr_interp == 0x2), 370 m_curr_packet_in->exception_info.exceptionType) == 0) 371 bAllocErr = true; 372 else 373 m_elem_pending_addr = true; // wait for following packets before marking for commit. 374 } 375 break; 376 377 case ETM4_PKT_I_EXCEPT_RTN: 378 { 379 // P0 element if V7M profile. 380 bool bV7MProfile = (m_config->archVersion() == ARCH_V7) && (m_config->coreProfile() == profile_CortexM); 381 if (m_P0_stack.createParamElemNoParam(P0_EXCEP_RET, bV7MProfile, m_curr_packet_in->getType(), m_index_curr_pkt) == 0) 382 bAllocErr = true; 383 else if (bV7MProfile) 384 m_curr_spec_depth++; 385 } 386 break; 387 388 case ETM4_PKT_I_FUNC_RET: 389 { 390 // P0 element iff V8M profile, otherwise ignore 391 if (OCSD_IS_V8_ARCH(m_config->archVersion()) && (m_config->coreProfile() == profile_CortexM)) 392 { 393 if (m_P0_stack.createParamElemNoParam(P0_FUNC_RET, true, m_curr_packet_in->getType(), m_index_curr_pkt) == 0) 394 bAllocErr = true; 395 else 396 m_curr_spec_depth++; 397 } 398 } 399 break; 400 401 // event trace 402 case ETM4_PKT_I_EVENT: 403 { 404 std::vector<uint32_t> params = { 0 }; 405 params[0] = (uint32_t)m_curr_packet_in->event_val; 406 if (m_P0_stack.createParamElem(P0_EVENT, false, m_curr_packet_in->getType(), m_index_curr_pkt, params) == 0) 407 bAllocErr = true; 408 409 } 410 break; 411 412 /* cycle count packets */ 413 case ETM4_PKT_I_CCNT_F1: 414 case ETM4_PKT_I_CCNT_F2: 415 case ETM4_PKT_I_CCNT_F3: 416 { 417 std::vector<uint32_t> params = { 0 }; 418 params[0] = m_curr_packet_in->getCC(); 419 if (m_P0_stack.createParamElem(P0_CC, false, m_curr_packet_in->getType(), m_index_curr_pkt, params) == 0) 420 bAllocErr = true; 421 422 } 423 break; 424 425 // timestamp 426 case ETM4_PKT_I_TIMESTAMP: 427 { 428 bool bTSwithCC = m_config->enabledCCI(); 429 uint64_t ts = m_curr_packet_in->getTS(); 430 std::vector<uint32_t> params = { 0, 0, 0 }; 431 params[0] = (uint32_t)(ts & 0xFFFFFFFF); 432 params[1] = (uint32_t)((ts >> 32) & 0xFFFFFFFF); 433 if (bTSwithCC) 434 params[2] = m_curr_packet_in->getCC(); 435 if (m_P0_stack.createParamElem(bTSwithCC ? P0_TS_CC : P0_TS, false, m_curr_packet_in->getType(), m_index_curr_pkt, params) == 0) 436 bAllocErr = true; 437 438 } 439 break; 440 441 case ETM4_PKT_I_BAD_SEQUENCE: 442 err = handleBadPacket("Bad byte sequence in packet."); 443 break; 444 445 case ETM4_PKT_I_BAD_TRACEMODE: 446 err = handleBadPacket("Invalid packet type for trace mode."); 447 break; 448 449 case ETM4_PKT_I_RESERVED: 450 err = handleBadPacket("Reserved packet header"); 451 break; 452 453 // speculation 454 case ETM4_PKT_I_MISPREDICT: 455 case ETM4_PKT_I_CANCEL_F1_MISPRED: 456 case ETM4_PKT_I_CANCEL_F2: 457 case ETM4_PKT_I_CANCEL_F3: 458 m_elem_res.mispredict = true; 459 if (m_curr_packet_in->getNumAtoms()) 460 { 461 if (m_P0_stack.createAtomElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getAtom()) == 0) 462 bAllocErr = true; 463 else 464 m_curr_spec_depth += m_curr_packet_in->getNumAtoms(); 465 } 466 467 case ETM4_PKT_I_CANCEL_F1: 468 m_elem_res.P0_cancel = m_curr_packet_in->getCancelElem(); 469 break; 470 471 case ETM4_PKT_I_COMMIT: 472 m_elem_res.P0_commit = m_curr_packet_in->getCommitElem(); 473 break; 474 475 case ETM4_PKT_I_OVERFLOW: 476 m_prev_overflow = true; 477 case ETM4_PKT_I_DISCARD: 478 m_curr_spec_depth = 0; 479 m_elem_res.discard = true; 480 break; 481 482 /* Q packets */ 483 case ETM4_PKT_I_Q: 484 { 485 TrcStackQElem *pQElem = m_P0_stack.createQElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->Q_pkt.q_count); 486 if (pQElem) 487 { 488 if (m_curr_packet_in->Q_pkt.addr_present) 489 { 490 etmv4_addr_val_t addr; 491 492 addr.val = m_curr_packet_in->getAddrVal(); 493 addr.isa = m_curr_packet_in->getAddrIS(); 494 pQElem->setAddr(addr); 495 m_curr_spec_depth++; 496 } 497 else 498 m_elem_pending_addr = true; 499 } 500 else 501 bAllocErr = true; 502 } 503 break; 504 505 /*** presently unsupported packets ***/ 506 /* conditional instruction tracing */ 507 case ETM4_PKT_I_COND_FLUSH: 508 case ETM4_PKT_I_COND_I_F1: 509 case ETM4_PKT_I_COND_I_F2: 510 case ETM4_PKT_I_COND_I_F3: 511 case ETM4_PKT_I_COND_RES_F1: 512 case ETM4_PKT_I_COND_RES_F2: 513 case ETM4_PKT_I_COND_RES_F3: 514 case ETM4_PKT_I_COND_RES_F4: 515 // data synchronisation markers 516 case ETM4_PKT_I_NUM_DS_MKR: 517 case ETM4_PKT_I_UNNUM_DS_MKR: 518 // all currently unsupported 519 { 520 ocsd_err_severity_t sev = OCSD_ERR_SEV_ERROR; 521 #ifdef OCSD_WARN_UNSUPPORTED 522 sev = OCSD_ERR_SEV_WARN; 523 //resp = OCSD_RESP_WARN_CONT; 524 #else 525 //resp = OCSD_RESP_FATAL_INVALID_DATA; 526 #endif 527 err = OCSD_ERR_UNSUPP_DECODE_PKT; 528 LogError(ocsdError(sev, err, "Data trace releated, unsupported packet type.")); 529 } 530 break; 531 532 default: 533 // any other packet - bad packet error 534 err = OCSD_ERR_BAD_DECODE_PKT; 535 LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,"Unknown packet type.")); 536 break; 537 } 538 539 // we need to wait for following address after certain packets 540 // - work out if we have seen enough here... 541 if (is_addr && m_elem_pending_addr) 542 { 543 m_curr_spec_depth++; // increase spec depth for element waiting on address. 544 m_elem_pending_addr = false; // can't be waiting on both 545 } 546 547 if(bAllocErr) 548 { 549 err = OCSD_ERR_MEM; 550 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_MEM,"Memory allocation error.")); 551 } 552 else if(m_curr_spec_depth > m_max_spec_depth) 553 { 554 // auto commit anything above max spec depth 555 // (this will auto commit anything if spec depth not supported!) 556 m_elem_res.P0_commit = m_curr_spec_depth - m_max_spec_depth; 557 } 558 559 if (!err && isElemForRes()) 560 m_curr_state = RESOLVE_ELEM; 561 return err; 562 } 563 564 void TrcPktDecodeEtmV4I::doTraceInfoPacket() 565 { 566 m_trace_info = m_curr_packet_in->getTraceInfo(); 567 m_cc_threshold = m_curr_packet_in->getCCThreshold(); 568 m_curr_spec_depth = m_curr_packet_in->getCurrSpecDepth(); 569 570 // elements associated with data trace 571 #ifdef DATA_TRACE_SUPPORTED 572 m_p0_key = m_curr_packet_in->getP0Key(); 573 #endif 574 } 575 576 /* Element resolution 577 * Commit or cancel elements as required 578 * Send any buffered output packets. 579 */ 580 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::resolveElements() 581 { 582 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 583 bool Complete = false; 584 585 while (!Complete) 586 { 587 if (m_out_elem.numElemToSend()) 588 resp = m_out_elem.sendElements(); 589 else if (isElemForRes()) 590 { 591 ocsd_err_t err = OCSD_OK; 592 if (m_elem_res.P0_commit) 593 err = commitElements(); 594 595 if (!err && m_elem_res.P0_cancel) 596 err = cancelElements(); 597 598 if (!err && m_elem_res.mispredict) 599 err = mispredictAtom(); 600 601 if (!err && m_elem_res.discard) 602 err = discardElements(); 603 604 if (err != OCSD_OK) 605 resp = OCSD_RESP_FATAL_INVALID_DATA; 606 } 607 608 // break out on error or wait request. 609 if (!OCSD_DATA_RESP_IS_CONT(resp)) 610 break; 611 612 // completion is nothing to send and nothing to commit 613 Complete = !m_out_elem.numElemToSend() && !isElemForRes(); 614 615 // done all elements - need more packets. 616 if (Complete) { 617 // if we are still in resolve, the goto decode. 618 if (m_curr_state == RESOLVE_ELEM) 619 m_curr_state = DECODE_PKTS; 620 } 621 } 622 return resp; 623 } 624 625 /* 626 * Walks through the element stack, processing from oldest element to the newest, 627 according to the number of P0 elements that need committing. 628 Build a stack of output elements in the process. 629 */ 630 ocsd_err_t TrcPktDecodeEtmV4I::commitElements() 631 { 632 ocsd_err_t err = OCSD_OK; 633 bool bPopElem = true; // do we remove the element from the stack (multi atom elements may need to stay!) 634 int num_commit_req = m_elem_res.P0_commit; 635 ocsd_trc_index_t err_idx = 0; 636 TrcStackElem *pElem = 0; // stacked element pointer 637 638 err = m_out_elem.resetElemStack(); 639 640 while(m_elem_res.P0_commit && !err) 641 { 642 if (m_P0_stack.size() > 0) 643 { 644 pElem = m_P0_stack.back(); // get oldest element 645 err_idx = pElem->getRootIndex(); // save index in case of error. 646 647 switch (pElem->getP0Type()) 648 { 649 // indicates a trace restart - beginning of trace or discontinuiuty 650 case P0_TRC_ON: 651 err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_TRACE_ON); 652 if (!err) 653 { 654 m_out_elem.getCurrElem().trace_on_reason = m_prev_overflow ? TRACE_ON_OVERFLOW : TRACE_ON_NORMAL; 655 m_prev_overflow = false; 656 m_return_stack.flush(); 657 } 658 break; 659 660 case P0_ADDR: 661 { 662 TrcStackElemAddr *pAddrElem = dynamic_cast<TrcStackElemAddr *>(pElem); 663 m_return_stack.clear_pop_pending(); // address removes the need to pop the indirect address target from the stack 664 if(pAddrElem) 665 { 666 SetInstrInfoInAddrISA(pAddrElem->getAddr().val, pAddrElem->getAddr().isa); 667 m_need_addr = false; 668 } 669 } 670 break; 671 672 case P0_CTXT: 673 { 674 TrcStackElemCtxt *pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem); 675 if(pCtxtElem) 676 { 677 etmv4_context_t ctxt = pCtxtElem->getContext(); 678 // check this is an updated context 679 if(ctxt.updated) 680 { 681 err = m_out_elem.addElem(pElem->getRootIndex()); 682 if (!err) 683 updateContext(pCtxtElem, outElem()); 684 } 685 } 686 } 687 break; 688 689 case P0_EVENT: 690 case P0_TS: 691 case P0_CC: 692 case P0_TS_CC: 693 err = processTS_CC_EventElem(pElem); 694 break; 695 696 case P0_ATOM: 697 { 698 TrcStackElemAtom *pAtomElem = dynamic_cast<TrcStackElemAtom *>(pElem); 699 700 if(pAtomElem) 701 { 702 while(!pAtomElem->isEmpty() && m_elem_res.P0_commit && !err) 703 { 704 ocsd_atm_val atom = pAtomElem->commitOldest(); 705 706 // check if prev atom left us an indirect address target on the return stack 707 if ((err = returnStackPop()) != OCSD_OK) 708 break; 709 710 // if address and context do instruction trace follower. 711 // otherwise skip atom and reduce committed elements 712 if(!m_need_ctxt && !m_need_addr) 713 { 714 err = processAtom(atom); 715 } 716 m_elem_res.P0_commit--; // mark committed 717 } 718 if(!pAtomElem->isEmpty()) 719 bPopElem = false; // don't remove if still atoms to process. 720 } 721 } 722 break; 723 724 case P0_EXCEP: 725 // check if prev atom left us an indirect address target on the return stack 726 if ((err = returnStackPop()) != OCSD_OK) 727 break; 728 729 err = processException(); // output trace + exception elements. 730 m_elem_res.P0_commit--; 731 break; 732 733 case P0_EXCEP_RET: 734 err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_EXCEPTION_RET); 735 if (!err) 736 { 737 if (pElem->isP0()) // are we on a core that counts ERET as P0? 738 m_elem_res.P0_commit--; 739 } 740 break; 741 742 case P0_FUNC_RET: 743 // func ret is V8M - data trace only - hint that data has been popped off the stack. 744 // at this point nothing to do till the decoder starts handling data trace. 745 if (pElem->isP0()) 746 m_elem_res.P0_commit--; 747 break; 748 749 case P0_Q: 750 err = processQElement(); 751 m_elem_res.P0_commit--; 752 break; 753 } 754 755 if(bPopElem) 756 m_P0_stack.delete_back(); // remove element from stack; 757 } 758 else 759 { 760 // too few elements for commit operation - decode error. 761 err = OCSD_ERR_COMMIT_PKT_OVERRUN; 762 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_COMMIT_PKT_OVERRUN,err_idx,m_CSID,"Not enough elements to commit")); 763 } 764 } 765 766 // reduce the spec depth by number of comitted elements 767 m_curr_spec_depth -= (num_commit_req-m_elem_res.P0_commit); 768 return err; 769 } 770 771 ocsd_err_t TrcPktDecodeEtmV4I::returnStackPop() 772 { 773 ocsd_err_t err = OCSD_OK; 774 ocsd_isa nextISA; 775 776 if (m_return_stack.pop_pending()) 777 { 778 ocsd_vaddr_t popAddr = m_return_stack.pop(nextISA); 779 if (m_return_stack.overflow()) 780 { 781 err = OCSD_ERR_RET_STACK_OVERFLOW; 782 LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, "Trace Return Stack Overflow.")); 783 } 784 else 785 { 786 m_instr_info.instr_addr = popAddr; 787 m_instr_info.isa = nextISA; 788 m_need_addr = false; 789 } 790 } 791 return err; 792 } 793 794 ocsd_err_t TrcPktDecodeEtmV4I::commitElemOnEOT() 795 { 796 ocsd_err_t err = OCSD_OK; 797 TrcStackElem *pElem = 0; 798 799 // nothing outstanding - reset the stack before we add more 800 if (!m_out_elem.numElemToSend()) 801 m_out_elem.resetElemStack(); 802 803 while((m_P0_stack.size() > 0) && !err) 804 { 805 // scan for outstanding events, TS and CC, that appear before any outstanding 806 // uncommited P0 element. 807 pElem = m_P0_stack.back(); 808 809 switch(pElem->getP0Type()) 810 { 811 // clear stack and stop 812 case P0_UNKNOWN: 813 case P0_ATOM: 814 case P0_TRC_ON: 815 case P0_EXCEP: 816 case P0_EXCEP_RET: 817 case P0_OVERFLOW: 818 case P0_Q: 819 m_P0_stack.delete_all(); 820 break; 821 822 //skip 823 case P0_ADDR: 824 case P0_CTXT: 825 break; 826 827 // output 828 case P0_EVENT: 829 case P0_TS: 830 case P0_CC: 831 case P0_TS_CC: 832 err = processTS_CC_EventElem(pElem); 833 break; 834 } 835 m_P0_stack.delete_back(); 836 } 837 838 if(!err) 839 { 840 err = m_out_elem.addElemType(m_index_curr_pkt, OCSD_GEN_TRC_ELEM_EO_TRACE); 841 outElem().setUnSyncEOTReason(m_prev_overflow ? UNSYNC_OVERFLOW : UNSYNC_EOT); 842 } 843 return err; 844 } 845 846 // cancel elements. These not output 847 ocsd_err_t TrcPktDecodeEtmV4I::cancelElements() 848 { 849 ocsd_err_t err = OCSD_OK; 850 bool P0StackDone = false; // checked all P0 elements on the stack 851 TrcStackElem *pElem = 0; // stacked element pointer 852 EtmV4P0Stack temp; 853 int num_cancel_req = m_elem_res.P0_cancel; 854 855 while (m_elem_res.P0_cancel) 856 { 857 //search the stack for the newest elements 858 if (!P0StackDone) 859 { 860 if (m_P0_stack.size() == 0) 861 P0StackDone = true; 862 else 863 { 864 // get the newest element 865 pElem = m_P0_stack.front(); 866 if (pElem->isP0()) { 867 if (pElem->getP0Type() == P0_ATOM) 868 { 869 TrcStackElemAtom *pAtomElem = (TrcStackElemAtom *)pElem; 870 // atom - cancel N atoms 871 m_elem_res.P0_cancel -= pAtomElem->cancelNewest(m_elem_res.P0_cancel); 872 if (pAtomElem->isEmpty()) 873 m_P0_stack.delete_front(); // remove the element 874 } 875 else 876 { 877 m_elem_res.P0_cancel--; 878 m_P0_stack.delete_front(); // remove the element 879 } 880 } else { 881 // not P0, make a keep / remove decision 882 switch (pElem->getP0Type()) 883 { 884 // keep these 885 case P0_EVENT: 886 case P0_TS: 887 case P0_CC: 888 case P0_TS_CC: 889 m_P0_stack.pop_front(false); 890 temp.push_back(pElem); 891 break; 892 893 default: 894 m_P0_stack.delete_front(); 895 break; 896 } 897 } 898 } 899 } 900 // may have some unseen elements 901 else if (m_unseen_spec_elem) 902 { 903 m_unseen_spec_elem--; 904 m_elem_res.P0_cancel--; 905 } 906 // otherwise we have some sort of overrun 907 else 908 { 909 // too few elements for commit operation - decode error. 910 err = OCSD_ERR_COMMIT_PKT_OVERRUN; 911 LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, m_index_curr_pkt, m_CSID, "Not enough elements to cancel")); 912 m_elem_res.P0_cancel = 0; 913 break; 914 } 915 916 if (temp.size()) 917 { 918 while (temp.size()) 919 { 920 pElem = temp.back(); 921 m_P0_stack.push_front(pElem); 922 temp.pop_back(false); 923 } 924 } 925 } 926 m_curr_spec_depth -= num_cancel_req - m_elem_res.P0_cancel; 927 return err; 928 } 929 930 // mispredict an atom 931 ocsd_err_t TrcPktDecodeEtmV4I::mispredictAtom() 932 { 933 ocsd_err_t err = OCSD_OK; 934 bool bFoundAtom = false, bDone = false; 935 TrcStackElem *pElem = 0; 936 937 m_P0_stack.from_front_init(); // init iterator at front. 938 while (!bDone) 939 { 940 pElem = m_P0_stack.from_front_next(); 941 if (pElem) 942 { 943 if (pElem->getP0Type() == P0_ATOM) 944 { 945 TrcStackElemAtom *pAtomElem = dynamic_cast<TrcStackElemAtom *>(pElem); 946 if (pAtomElem) 947 { 948 pAtomElem->mispredictNewest(); 949 bFoundAtom = true; 950 } 951 bDone = true; 952 } 953 else if (pElem->getP0Type() == P0_ADDR) 954 { 955 // need to disregard any addresses that appear between mispredict and the atom in question 956 m_P0_stack.erase_curr_from_front(); 957 } 958 } 959 else 960 bDone = true; 961 } 962 963 // if missed atom then either overrun error or mispredict on unseen element 964 if (!bFoundAtom && !m_unseen_spec_elem) 965 { 966 err = OCSD_ERR_COMMIT_PKT_OVERRUN; 967 LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, m_index_curr_pkt, m_CSID, "Not found mispredict atom")); 968 } 969 m_elem_res.mispredict = false; 970 return err; 971 } 972 973 // discard elements and flush 974 ocsd_err_t TrcPktDecodeEtmV4I::discardElements() 975 { 976 ocsd_err_t err = OCSD_OK; 977 TrcStackElem *pElem = 0; // stacked element pointer 978 979 // dump P0, elemnts - output remaining CC / TS 980 while ((m_P0_stack.size() > 0) && !err) 981 { 982 pElem = m_P0_stack.back(); 983 err = processTS_CC_EventElem(pElem); 984 m_P0_stack.delete_back(); 985 } 986 987 // clear all speculation info 988 clearElemRes(); 989 m_curr_spec_depth = 0; 990 991 // set decode state 992 m_curr_state = NO_SYNC; 993 m_unsync_eot_info = m_prev_overflow ? UNSYNC_OVERFLOW : UNSYNC_DISCARD; 994 995 // unsync so need context & address. 996 m_need_ctxt = true; 997 m_need_addr = true; 998 m_elem_pending_addr = false; 999 return err; 1000 } 1001 1002 ocsd_err_t TrcPktDecodeEtmV4I::processTS_CC_EventElem(TrcStackElem *pElem) 1003 { 1004 ocsd_err_t err = OCSD_OK; 1005 1006 switch (pElem->getP0Type()) 1007 { 1008 case P0_EVENT: 1009 { 1010 TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem); 1011 if (pParamElem) 1012 err = addElemEvent(pParamElem); 1013 } 1014 break; 1015 1016 case P0_TS: 1017 { 1018 TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem); 1019 if (pParamElem) 1020 err = addElemTS(pParamElem, false); 1021 } 1022 break; 1023 1024 case P0_CC: 1025 { 1026 TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem); 1027 if (pParamElem) 1028 err = addElemCC(pParamElem); 1029 } 1030 break; 1031 1032 case P0_TS_CC: 1033 { 1034 TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem); 1035 if (pParamElem) 1036 err = addElemTS(pParamElem, true); 1037 } 1038 break; 1039 } 1040 return err; 1041 1042 } 1043 1044 ocsd_err_t TrcPktDecodeEtmV4I::addElemCC(TrcStackElemParam *pParamElem) 1045 { 1046 ocsd_err_t err = OCSD_OK; 1047 1048 err = m_out_elem.addElemType(pParamElem->getRootIndex(), OCSD_GEN_TRC_ELEM_CYCLE_COUNT); 1049 if (!err) 1050 outElem().setCycleCount(pParamElem->getParam(0)); 1051 return err; 1052 } 1053 1054 ocsd_err_t TrcPktDecodeEtmV4I::addElemTS(TrcStackElemParam *pParamElem, bool withCC) 1055 { 1056 ocsd_err_t err = OCSD_OK; 1057 1058 err = m_out_elem.addElemType(pParamElem->getRootIndex(), OCSD_GEN_TRC_ELEM_TIMESTAMP); 1059 if (!err) 1060 { 1061 outElem().timestamp = (uint64_t)(pParamElem->getParam(0)) | (((uint64_t)pParamElem->getParam(1)) << 32); 1062 if (withCC) 1063 outElem().setCycleCount(pParamElem->getParam(2)); 1064 } 1065 return err; 1066 } 1067 1068 ocsd_err_t TrcPktDecodeEtmV4I::addElemEvent(TrcStackElemParam *pParamElem) 1069 { 1070 ocsd_err_t err = OCSD_OK; 1071 1072 err = m_out_elem.addElemType(pParamElem->getRootIndex(), OCSD_GEN_TRC_ELEM_EVENT); 1073 if (!err) 1074 { 1075 outElem().trace_event.ev_type = EVENT_NUMBERED; 1076 outElem().trace_event.ev_number = pParamElem->getParam(0); 1077 } 1078 return err; 1079 } 1080 1081 void TrcPktDecodeEtmV4I::setElemTraceRange(OcsdTraceElement &elemIn, const instr_range_t &addr_range, 1082 const bool executed, ocsd_trc_index_t index) 1083 { 1084 elemIn.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE); 1085 elemIn.setLastInstrInfo(executed, m_instr_info.type, m_instr_info.sub_type, m_instr_info.instr_size); 1086 elemIn.setISA(m_instr_info.isa); 1087 elemIn.setLastInstrCond(m_instr_info.is_conditional); 1088 elemIn.setAddrRange(addr_range.st_addr, addr_range.en_addr, addr_range.num_instr); 1089 if (executed) 1090 m_instr_info.isa = m_instr_info.next_isa; 1091 } 1092 1093 ocsd_err_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom) 1094 { 1095 ocsd_err_t err; 1096 TrcStackElem *pElem = m_P0_stack.back(); // get the atom element 1097 WP_res_t WPRes; 1098 instr_range_t addr_range; 1099 1100 // new element for this processed atom 1101 if ((err = m_out_elem.addElem(pElem->getRootIndex())) != OCSD_OK) 1102 return err; 1103 1104 err = traceInstrToWP(addr_range, WPRes); 1105 if(err != OCSD_OK) 1106 { 1107 if(err == OCSD_ERR_UNSUPPORTED_ISA) 1108 { 1109 m_need_addr = true; 1110 m_need_ctxt = true; 1111 LogError(ocsdError(OCSD_ERR_SEV_WARN,err,pElem->getRootIndex(),m_CSID,"Warning: unsupported instruction set processing atom packet.")); 1112 // wait for next context 1113 return OCSD_OK; 1114 } 1115 else 1116 { 1117 LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,pElem->getRootIndex(),m_CSID,"Error processing atom packet.")); 1118 return err; 1119 } 1120 } 1121 1122 if(WPFound(WPRes)) 1123 { 1124 // save recorded next instuction address 1125 ocsd_vaddr_t nextAddr = m_instr_info.instr_addr; 1126 1127 // action according to waypoint type and atom value 1128 switch(m_instr_info.type) 1129 { 1130 case OCSD_INSTR_BR: 1131 if (atom == ATOM_E) 1132 { 1133 m_instr_info.instr_addr = m_instr_info.branch_addr; 1134 if (m_instr_info.is_link) 1135 m_return_stack.push(nextAddr, m_instr_info.isa); 1136 1137 } 1138 break; 1139 1140 case OCSD_INSTR_BR_INDIRECT: 1141 if (atom == ATOM_E) 1142 { 1143 m_need_addr = true; // indirect branch taken - need new address. 1144 if (m_instr_info.is_link) 1145 m_return_stack.push(nextAddr,m_instr_info.isa); 1146 m_return_stack.set_pop_pending(); // need to know next packet before we know what is to happen 1147 } 1148 break; 1149 } 1150 setElemTraceRange(outElem(), addr_range, (atom == ATOM_E), pElem->getRootIndex()); 1151 } 1152 else 1153 { 1154 // no waypoint - likely inaccessible memory range. 1155 m_need_addr = true; // need an address update 1156 1157 if(addr_range.st_addr != addr_range.en_addr) 1158 { 1159 // some trace before we were out of memory access range 1160 setElemTraceRange(outElem(), addr_range, true, pElem->getRootIndex()); 1161 1162 // another element for the nacc... 1163 if (WPNacc(WPRes)) 1164 err = m_out_elem.addElem(pElem->getRootIndex()); 1165 } 1166 1167 if(WPNacc(WPRes) && !err) 1168 { 1169 outElem().setType(OCSD_GEN_TRC_ELEM_ADDR_NACC); 1170 outElem().st_addr = m_instr_info.instr_addr; 1171 } 1172 } 1173 return err; 1174 } 1175 1176 // Exception processor 1177 ocsd_err_t TrcPktDecodeEtmV4I::processException() 1178 { 1179 ocsd_err_t err; 1180 TrcStackElem *pElem = 0; 1181 TrcStackElemExcept *pExceptElem = 0; 1182 TrcStackElemAddr *pAddressElem = 0; 1183 TrcStackElemCtxt *pCtxtElem = 0; 1184 bool branch_target = false; // exception address implies prior branch target address 1185 ocsd_vaddr_t excep_ret_addr; 1186 ocsd_trc_index_t excep_pkt_index; 1187 WP_res_t WPRes = WP_NOT_FOUND; 1188 1189 // grab the exception element off the stack 1190 pExceptElem = dynamic_cast<TrcStackElemExcept *>(m_P0_stack.back()); // get the exception element 1191 excep_pkt_index = pExceptElem->getRootIndex(); 1192 branch_target = pExceptElem->getPrevSame(); 1193 m_P0_stack.pop_back(); // remove the exception element 1194 1195 pElem = m_P0_stack.back(); // look at next element. 1196 if(pElem->getP0Type() == P0_CTXT) 1197 { 1198 pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem); 1199 m_P0_stack.pop_back(); // remove the context element 1200 pElem = m_P0_stack.back(); // next one should be an address element 1201 } 1202 1203 if(pElem->getP0Type() != P0_ADDR) 1204 { 1205 // no following address element - indicate processing error. 1206 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ, excep_pkt_index,m_CSID,"Address missing in exception packet.")); 1207 return OCSD_ERR_BAD_PACKET_SEQ; 1208 } 1209 else 1210 { 1211 // extract address 1212 pAddressElem = static_cast<TrcStackElemAddr *>(pElem); 1213 excep_ret_addr = pAddressElem->getAddr().val; 1214 1215 // see if there is an address + optional context element implied 1216 // prior to the exception. 1217 if (branch_target) 1218 { 1219 // this was a branch target address - update current setting 1220 bool b64bit = m_instr_info.isa == ocsd_isa_aarch64; 1221 if (pCtxtElem) { 1222 b64bit = pCtxtElem->getContext().SF; 1223 } 1224 1225 // as the exception address was also a branch target address then update the 1226 // current maintained address value. This also means that there is no range to 1227 // output before the exception packet. 1228 m_instr_info.instr_addr = excep_ret_addr; 1229 m_instr_info.isa = (pAddressElem->getAddr().isa == 0) ? 1230 (b64bit ? ocsd_isa_aarch64 : ocsd_isa_arm) : ocsd_isa_thumb2; 1231 m_need_addr = false; 1232 } 1233 } 1234 1235 // need to output something - set up an element 1236 if ((err = m_out_elem.addElem(excep_pkt_index))) 1237 return err; 1238 1239 // output a context element if present 1240 if (pCtxtElem) 1241 { 1242 updateContext(pCtxtElem, outElem()); 1243 1244 // used the element - need another for later stages 1245 if ((err = m_out_elem.addElem(excep_pkt_index))) 1246 return err; 1247 } 1248 1249 // if the preferred return address is not the end of the last output range... 1250 if (m_instr_info.instr_addr != excep_ret_addr) 1251 { 1252 bool range_out = false; 1253 instr_range_t addr_range; 1254 1255 // look for match to return address. 1256 err = traceInstrToWP(addr_range, WPRes, true, excep_ret_addr); 1257 1258 if(err != OCSD_OK) 1259 { 1260 if(err == OCSD_ERR_UNSUPPORTED_ISA) 1261 { 1262 m_need_addr = true; 1263 m_need_ctxt = true; 1264 LogError(ocsdError(OCSD_ERR_SEV_WARN,err, excep_pkt_index,m_CSID,"Warning: unsupported instruction set processing exception packet.")); 1265 } 1266 else 1267 { 1268 LogError(ocsdError(OCSD_ERR_SEV_ERROR,err, excep_pkt_index,m_CSID,"Error processing exception packet.")); 1269 } 1270 return err; 1271 } 1272 1273 if(WPFound(WPRes)) 1274 { 1275 // waypoint address found - output range 1276 setElemTraceRange(outElem(), addr_range, true, excep_pkt_index); 1277 range_out = true; 1278 } 1279 else 1280 { 1281 // no waypoint - likely inaccessible memory range. 1282 m_need_addr = true; // need an address update 1283 1284 if(addr_range.st_addr != addr_range.en_addr) 1285 { 1286 // some trace before we were out of memory access range 1287 setElemTraceRange(outElem(), addr_range, true, excep_pkt_index); 1288 range_out = true; 1289 } 1290 } 1291 1292 // used the element need another for NACC or EXCEP. 1293 if (range_out) 1294 { 1295 if ((err = m_out_elem.addElem(excep_pkt_index))) 1296 return err; 1297 } 1298 } 1299 1300 // watchpoint walk resulted in inaccessible memory call... 1301 if (WPNacc(WPRes)) 1302 { 1303 1304 outElem().setType(OCSD_GEN_TRC_ELEM_ADDR_NACC); 1305 outElem().st_addr = m_instr_info.instr_addr; 1306 1307 // used the element - need another for the final exception packet. 1308 if ((err = m_out_elem.addElem(excep_pkt_index))) 1309 return err; 1310 } 1311 1312 // output exception element. 1313 outElem().setType(OCSD_GEN_TRC_ELEM_EXCEPTION); 1314 1315 // add end address as preferred return address to end addr in element 1316 outElem().en_addr = excep_ret_addr; 1317 outElem().excep_ret_addr = 1; 1318 outElem().excep_ret_addr_br_tgt = branch_target; 1319 outElem().exception_number = pExceptElem->getExcepNum(); 1320 1321 m_P0_stack.delete_popped(); // clear the used elements from the stack 1322 return err; 1323 } 1324 1325 ocsd_err_t TrcPktDecodeEtmV4I::processQElement() 1326 { 1327 ocsd_err_t err = OCSD_OK; 1328 TrcStackQElem *pQElem; 1329 etmv4_addr_val_t QAddr; // address where trace restarts 1330 int iCount = 0; 1331 1332 pQElem = dynamic_cast<TrcStackQElem *>(m_P0_stack.back()); // get the exception element 1333 m_P0_stack.pop_back(); // remove the Q element. 1334 1335 if (!pQElem->hasAddr()) // no address - it must be next on the stack.... 1336 { 1337 TrcStackElemAddr *pAddressElem = 0; 1338 TrcStackElemCtxt *pCtxtElem = 0; 1339 TrcStackElem *pElem = 0; 1340 1341 pElem = m_P0_stack.back(); // look at next element. 1342 if (pElem->getP0Type() == P0_CTXT) 1343 { 1344 pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem); 1345 m_P0_stack.pop_back(); // remove the context element 1346 pElem = m_P0_stack.back(); // next one should be an address element 1347 } 1348 1349 if (pElem->getP0Type() != P0_ADDR) 1350 { 1351 // no following address element - indicate processing error. 1352 err = OCSD_ERR_BAD_PACKET_SEQ; 1353 LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pQElem->getRootIndex(), m_CSID, "Address missing in Q packet.")); 1354 m_P0_stack.delete_popped(); 1355 return err; 1356 } 1357 pAddressElem = dynamic_cast<TrcStackElemAddr *>(pElem); 1358 QAddr = pAddressElem->getAddr(); 1359 m_P0_stack.pop_back(); // remove the address element 1360 m_P0_stack.delete_popped(); // clear used elements 1361 1362 // return the context element for processing next time. 1363 if (pCtxtElem) 1364 { 1365 // need a new copy at the back - old one will be deleted as popped. 1366 m_P0_stack.createContextElem(pCtxtElem->getRootPkt(), pCtxtElem->getRootIndex(), pCtxtElem->getContext(),true); 1367 } 1368 } 1369 else 1370 QAddr = pQElem->getAddr(); 1371 1372 // process the Q element with address. 1373 iCount = pQElem->getInstrCount(); 1374 1375 bool isBranch = false; 1376 1377 // need to output something - set up an element 1378 if ((err = m_out_elem.addElem(pQElem->getRootIndex()))) 1379 return err; 1380 1381 instr_range_t addr_range; 1382 addr_range.st_addr = addr_range.en_addr = m_instr_info.instr_addr; 1383 addr_range.num_instr = 0; 1384 1385 // walk iCount instructions 1386 for (int i = 0; i < iCount; i++) 1387 { 1388 uint32_t opcode; 1389 uint32_t bytesReq = 4; 1390 1391 err = accessMemory(m_instr_info.instr_addr, getCurrMemSpace(), &bytesReq, (uint8_t *)&opcode); 1392 if (err != OCSD_OK) break; 1393 1394 if (bytesReq == 4) // got data back 1395 { 1396 m_instr_info.opcode = opcode; 1397 err = instrDecode(&m_instr_info); 1398 if (err != OCSD_OK) break; 1399 1400 // increment address - may be adjusted by direct branch value later 1401 m_instr_info.instr_addr += m_instr_info.instr_size; 1402 addr_range.num_instr++; 1403 1404 isBranch = (m_instr_info.type == OCSD_INSTR_BR) || 1405 (m_instr_info.type == OCSD_INSTR_BR_INDIRECT); 1406 1407 // on a branch no way of knowing if taken - bail out 1408 if (isBranch) 1409 break; 1410 } 1411 else 1412 break; // missing memory 1413 1414 } 1415 1416 if (err == OCSD_OK) 1417 { 1418 bool inCompleteRange = true; 1419 if (iCount && (addr_range.num_instr == (unsigned)iCount)) 1420 { 1421 if ((m_instr_info.instr_addr == QAddr.val) || // complete range 1422 (isBranch)) // or ends on branch - only way we know if branch taken. 1423 { 1424 // output a range and continue 1425 inCompleteRange = false; 1426 // update the range decoded address in the output packet. 1427 addr_range.en_addr = m_instr_info.instr_addr; 1428 setElemTraceRange(outElem(), addr_range, true, pQElem->getRootIndex()); 1429 } 1430 } 1431 1432 if (inCompleteRange) 1433 { 1434 // unknown instructions executed. 1435 addr_range.en_addr = QAddr.val; 1436 addr_range.num_instr = iCount; 1437 1438 outElem().setType(OCSD_GEN_TRC_ELEM_I_RANGE_NOPATH); 1439 outElem().setAddrRange(addr_range.st_addr, addr_range.en_addr, addr_range.num_instr); 1440 outElem().setISA(calcISA(m_is_64bit, QAddr.isa)); 1441 } 1442 1443 // after the Q element, tracing resumes at the address supplied 1444 SetInstrInfoInAddrISA(QAddr.val, QAddr.isa); 1445 m_need_addr = false; 1446 } 1447 else 1448 { 1449 // output error and halt decode. 1450 LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, pQElem->getRootIndex(), m_CSID, "Error processing Q packet")); 1451 } 1452 m_P0_stack.delete_popped(); 1453 return err; 1454 } 1455 1456 void TrcPktDecodeEtmV4I::SetInstrInfoInAddrISA(const ocsd_vaddr_t addr_val, const uint8_t isa) 1457 { 1458 m_instr_info.instr_addr = addr_val; 1459 m_instr_info.isa = calcISA(m_is_64bit, isa); 1460 } 1461 1462 // trace an instruction range to a waypoint - and set next address to restart from. 1463 ocsd_err_t TrcPktDecodeEtmV4I::traceInstrToWP(instr_range_t &range, WP_res_t &WPRes, const bool traceToAddrNext /*= false*/, const ocsd_vaddr_t nextAddrMatch /*= 0*/) 1464 { 1465 uint32_t opcode; 1466 uint32_t bytesReq; 1467 ocsd_err_t err = OCSD_OK; 1468 1469 range.st_addr = range.en_addr = m_instr_info.instr_addr; 1470 range.num_instr = 0; 1471 1472 WPRes = WP_NOT_FOUND; 1473 1474 while(WPRes == WP_NOT_FOUND) 1475 { 1476 // start off by reading next opcode; 1477 bytesReq = 4; 1478 err = accessMemory(m_instr_info.instr_addr, getCurrMemSpace(),&bytesReq,(uint8_t *)&opcode); 1479 if(err != OCSD_OK) break; 1480 1481 if(bytesReq == 4) // got data back 1482 { 1483 m_instr_info.opcode = opcode; 1484 err = instrDecode(&m_instr_info); 1485 if(err != OCSD_OK) break; 1486 1487 // increment address - may be adjusted by direct branch value later 1488 m_instr_info.instr_addr += m_instr_info.instr_size; 1489 range.num_instr++; 1490 1491 // either walking to match the next instruction address or a real watchpoint 1492 if (traceToAddrNext) 1493 { 1494 if (m_instr_info.instr_addr == nextAddrMatch) 1495 WPRes = WP_FOUND; 1496 } 1497 else if (m_instr_info.type != OCSD_INSTR_OTHER) 1498 WPRes = WP_FOUND; 1499 } 1500 else 1501 { 1502 // not enough memory accessible. 1503 WPRes = WP_NACC; 1504 } 1505 } 1506 // update the range decoded address in the output packet. 1507 range.en_addr = m_instr_info.instr_addr; 1508 return err; 1509 } 1510 1511 void TrcPktDecodeEtmV4I::updateContext(TrcStackElemCtxt *pCtxtElem, OcsdTraceElement &elem) 1512 { 1513 etmv4_context_t ctxt = pCtxtElem->getContext(); 1514 1515 elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT); 1516 1517 // map to output element and local saved state. 1518 m_is_64bit = (ctxt.SF != 0); 1519 elem.context.bits64 = ctxt.SF; 1520 m_is_secure = (ctxt.NS == 0); 1521 elem.context.security_level = ctxt.NS ? ocsd_sec_nonsecure : ocsd_sec_secure; 1522 elem.context.exception_level = (ocsd_ex_level)ctxt.EL; 1523 elem.context.el_valid = 1; 1524 if(ctxt.updated_c) 1525 { 1526 elem.context.ctxt_id_valid = 1; 1527 m_context_id = elem.context.context_id = ctxt.ctxtID; 1528 } 1529 if(ctxt.updated_v) 1530 { 1531 elem.context.vmid_valid = 1; 1532 m_vmid_id = elem.context.vmid = ctxt.VMID; 1533 } 1534 1535 // need to update ISA in case context follows address. 1536 elem.isa = m_instr_info.isa = calcISA(m_is_64bit, pCtxtElem->getIS()); 1537 m_need_ctxt = false; 1538 } 1539 1540 ocsd_err_t TrcPktDecodeEtmV4I::handleBadPacket(const char *reason) 1541 { 1542 ocsd_err_t err = OCSD_OK; 1543 1544 if(getComponentOpMode() & OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS) 1545 { 1546 // error out - stop decoding 1547 err = OCSD_ERR_BAD_DECODE_PKT; 1548 LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,reason)); 1549 } 1550 else 1551 { 1552 LogError(ocsdError(OCSD_ERR_SEV_WARN, OCSD_ERR_BAD_DECODE_PKT, reason)); 1553 // switch to unsync - clear decode state 1554 resetDecoder(); 1555 m_curr_state = NO_SYNC; 1556 m_unsync_eot_info = UNSYNC_BAD_PACKET; 1557 } 1558 return err; 1559 } 1560 1561 inline ocsd_mem_space_acc_t TrcPktDecodeEtmV4I::getCurrMemSpace() 1562 { 1563 static ocsd_mem_space_acc_t SMemSpace[] = { 1564 OCSD_MEM_SPACE_EL1S, 1565 OCSD_MEM_SPACE_EL1S, 1566 OCSD_MEM_SPACE_EL2S, 1567 OCSD_MEM_SPACE_EL3 1568 }; 1569 1570 static ocsd_mem_space_acc_t NSMemSpace[] = { 1571 OCSD_MEM_SPACE_EL1N, 1572 OCSD_MEM_SPACE_EL1N, 1573 OCSD_MEM_SPACE_EL2, 1574 OCSD_MEM_SPACE_EL3 1575 }; 1576 1577 /* if no valid EL value - just use S/NS */ 1578 if (!outElem().context.el_valid) 1579 return m_is_secure ? OCSD_MEM_SPACE_S : OCSD_MEM_SPACE_N; 1580 1581 /* mem space according to EL + S/NS */ 1582 int el = (int)(outElem().context.exception_level) & 0x3; 1583 return m_is_secure ? SMemSpace[el] : NSMemSpace[el]; 1584 } 1585 /* End of File trc_pkt_decode_etmv4i.cpp */ 1586