1 /* 2 * \file trc_pkt_proc_etmv3_impl.cpp 3 * \brief OpenCSD : 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 "trc_pkt_proc_etmv3_impl.h" 36 37 EtmV3PktProcImpl::EtmV3PktProcImpl() : 38 m_isInit(false), 39 m_interface(0) 40 { 41 } 42 43 EtmV3PktProcImpl::~EtmV3PktProcImpl() 44 { 45 } 46 47 ocsd_err_t EtmV3PktProcImpl::Configure(const EtmV3Config *p_config) 48 { 49 ocsd_err_t err = OCSD_OK; 50 if(p_config != 0) 51 { 52 m_config = *p_config; 53 m_chanIDCopy = m_config.getTraceID(); 54 } 55 else 56 { 57 err = OCSD_ERR_INVALID_PARAM_VAL; 58 if(m_isInit) 59 m_interface->LogError(ocsdError(OCSD_ERR_SEV_ERROR,err)); 60 } 61 return err; 62 } 63 64 ocsd_datapath_resp_t EtmV3PktProcImpl::processData(const ocsd_trc_index_t index, 65 const uint32_t dataBlockSize, 66 const uint8_t *pDataBlock, 67 uint32_t *numBytesProcessed) 68 { 69 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 70 m_bytesProcessed = 0; 71 72 while( ( (m_bytesProcessed < dataBlockSize) || 73 ((m_bytesProcessed == dataBlockSize) && (m_process_state == SEND_PKT)) ) 74 && OCSD_DATA_RESP_IS_CONT(resp)) 75 { 76 try 77 { 78 switch(m_process_state) 79 { 80 case WAIT_SYNC: 81 if(!m_bStartOfSync) 82 m_packet_index = index + m_bytesProcessed; 83 m_bytesProcessed += waitForSync(dataBlockSize-m_bytesProcessed,pDataBlock+m_bytesProcessed); 84 break; 85 86 case PROC_HDR: 87 m_packet_index = index + m_bytesProcessed; 88 processHeaderByte(pDataBlock[m_bytesProcessed++]); 89 break; 90 91 case PROC_DATA: 92 processPayloadByte(pDataBlock [m_bytesProcessed++]); 93 break; 94 95 case SEND_PKT: 96 resp = outputPacket(); 97 break; 98 } 99 } 100 catch(ocsdError &err) 101 { 102 m_interface->LogError(err); 103 if( (err.getErrorCode() == OCSD_ERR_BAD_PACKET_SEQ) || 104 (err.getErrorCode() == OCSD_ERR_INVALID_PCKT_HDR)) 105 { 106 // send invalid packets up the pipe to let the next stage decide what to do. 107 m_process_state = SEND_PKT; 108 } 109 else 110 { 111 // bail out on any other error. 112 resp = OCSD_RESP_FATAL_INVALID_DATA; 113 } 114 } 115 catch(...) 116 { 117 /// vv bad at this point. 118 resp = OCSD_RESP_FATAL_SYS_ERR; 119 ocsdError fatal = ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_FAIL,m_packet_index,m_chanIDCopy); 120 fatal.setMessage("Unknown System Error decoding trace."); 121 m_interface->LogError(fatal); 122 } 123 } 124 125 *numBytesProcessed = m_bytesProcessed; 126 return resp; 127 } 128 129 ocsd_datapath_resp_t EtmV3PktProcImpl::onEOT() 130 { 131 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 132 // if we have a partial packet then send to attached sinks 133 if(m_currPacketData.size() != 0) 134 { 135 // TBD: m_curr_packet.updateErrType(ETM4_ETM3_PKT_I_INCOMPLETE_EOT); 136 resp = outputPacket(); 137 InitPacketState(); 138 } 139 return resp; 140 } 141 142 ocsd_datapath_resp_t EtmV3PktProcImpl::onReset() 143 { 144 InitProcessorState(); 145 return OCSD_RESP_CONT; 146 } 147 148 ocsd_datapath_resp_t EtmV3PktProcImpl::onFlush() 149 { 150 // packet processor never holds on to flushable data (may have partial packet, 151 // but any full packets are immediately sent) 152 return OCSD_RESP_CONT; 153 } 154 155 void EtmV3PktProcImpl::Initialise(TrcPktProcEtmV3 *p_interface) 156 { 157 if(p_interface) 158 { 159 m_interface = p_interface; 160 m_isInit = true; 161 162 } 163 InitProcessorState(); 164 /* not using pattern matcher for sync at present 165 static const uint8_t a_sync[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 }; 166 m_syncMatch.setPattern(a_sync, sizeof(a_sync));*/ 167 } 168 169 void EtmV3PktProcImpl::InitProcessorState() 170 { 171 m_bStreamSync = false; // not synced 172 m_process_state = WAIT_SYNC; // waiting for sync 173 m_bStartOfSync = false; // not seen start of sync packet 174 m_curr_packet.ResetState(); // reset intra packet state 175 InitPacketState(); // set curr packet state 176 m_bSendPartPkt = false; 177 } 178 179 void EtmV3PktProcImpl::InitPacketState() 180 { 181 m_bytesExpectedThisPkt = 0; 182 m_BranchPktNeedsException = false; 183 m_bIsync_got_cycle_cnt = false; 184 m_bIsync_get_LSiP_addr = false; 185 m_IsyncInfoIdx = false; 186 m_bExpectingDataAddress = false; 187 m_bFoundDataAddress = false; 188 m_currPacketData.clear(); 189 m_currPktIdx = 0; // index into processed bytes in current packet 190 m_curr_packet.Clear(); 191 192 } 193 194 ocsd_datapath_resp_t EtmV3PktProcImpl::outputPacket() 195 { 196 ocsd_datapath_resp_t dp_resp = OCSD_RESP_FATAL_NOT_INIT; 197 if(m_isInit) 198 { 199 ocsd_etmv3_pkt_type type = m_curr_packet.getType(); 200 if(!m_bSendPartPkt) 201 { 202 dp_resp = m_interface->outputOnAllInterfaces(m_packet_index,&m_curr_packet,&type,m_currPacketData); 203 m_process_state = m_bStreamSync ? PROC_HDR : WAIT_SYNC; // need a header next time, or still waiting to sync. 204 m_currPacketData.clear(); 205 } 206 else 207 { 208 // sending part packet, still some data in the main packet 209 dp_resp = m_interface->outputOnAllInterfaces(m_packet_index,&m_curr_packet,&type,m_partPktData); 210 m_process_state = m_post_part_pkt_state; 211 m_packet_index += m_partPktData.size(); 212 m_bSendPartPkt = false; 213 m_curr_packet.SetType(m_post_part_pkt_type); 214 } 215 } 216 return dp_resp; 217 } 218 219 void EtmV3PktProcImpl::setBytesPartPkt(int numBytes, process_state nextState, const ocsd_etmv3_pkt_type nextType) 220 { 221 m_partPktData.clear(); 222 for(int i=0; i < numBytes; i++) 223 { 224 m_partPktData.push_back(m_currPacketData[i]); 225 } 226 m_currPacketData.erase(m_currPacketData.begin(), m_currPacketData.begin()+numBytes); 227 m_bSendPartPkt = true; 228 m_post_part_pkt_state = nextState; 229 m_post_part_pkt_type = nextType; 230 } 231 232 uint32_t EtmV3PktProcImpl::waitForSync(const uint32_t dataBlockSize, const uint8_t *pDataBlock) 233 { 234 uint8_t currByte; 235 uint32_t bytesProcessed = 0; 236 bool bSendBlock = false; 237 238 // need to wait for the first sync packet 239 while(!bSendBlock && (bytesProcessed < dataBlockSize)) 240 { 241 currByte = pDataBlock[bytesProcessed++]; 242 // TBD: forced sync point 243 244 if(m_bStartOfSync) 245 { 246 // need to handle consecutive 0 bytes followed by genuine A-SYNC. 247 248 m_currPacketData.push_back(currByte); 249 if((currByte == 0x80) && (m_currPacketData.size() >= 6)) 250 { 251 // it is a sync packet possibly with leading zeros 252 bSendBlock = true; 253 if(m_currPacketData.size() > 6) 254 { 255 m_currPacketData.pop_back(); 256 bytesProcessed--; // return 0x80 to the input buffer to re-process next pass after stripping 0's 257 setBytesPartPkt(m_currPacketData.size()-5,WAIT_SYNC,ETM3_PKT_NOTSYNC); 258 } 259 else 260 { 261 m_bStreamSync = true; 262 m_curr_packet.SetType(ETM3_PKT_A_SYNC); 263 } 264 } 265 else if(currByte != 0x00) 266 { 267 m_bStartOfSync = false; // not a sync packet 268 } 269 else if(m_currPacketData.size() >= 13) // 13 0's, strip 8 of them... 270 { 271 setBytesPartPkt(8,WAIT_SYNC,ETM3_PKT_NOTSYNC); 272 bSendBlock = true; 273 } 274 } 275 else // not seen a start of sync candidate yet 276 { 277 if(currByte == 0x00) // could be the start of a-sync 278 { 279 if(m_currPacketData.size() == 0) 280 { 281 m_currPacketData.push_back(currByte); 282 m_bStartOfSync = true; 283 } 284 else 285 { 286 bytesProcessed--; 287 bSendBlock = true; // send none sync packet data, re-process this byte next time. 288 m_curr_packet.SetType(ETM3_PKT_NOTSYNC); // send unsynced data packet. 289 } 290 } 291 else 292 { 293 //save a byte - not start of a-sync 294 m_currPacketData.push_back(currByte); 295 296 // done all data in this block, or got 16 unsynced bytes 297 if((bytesProcessed == dataBlockSize) || (m_currPacketData.size() == 16)) 298 { 299 bSendBlock = true; // send none sync packet block 300 m_curr_packet.SetType(ETM3_PKT_NOTSYNC); // send unsynced data packet. 301 } 302 } 303 } 304 } 305 if(bSendBlock) 306 SendPacket(); 307 return bytesProcessed; 308 } 309 310 ocsd_err_t EtmV3PktProcImpl::processHeaderByte(uint8_t by) 311 { 312 InitPacketState(); // new packet, clear old single packet state (retains intra packet state). 313 314 // save byte 315 m_currPacketData.push_back(by); 316 317 m_process_state = PROC_DATA; // assume next is data packet 318 319 // check for branch address 0bCxxxxxxx1 320 if((by & 0x01) == 0x01 ) { 321 m_curr_packet.SetType(ETM3_PKT_BRANCH_ADDRESS); 322 m_BranchPktNeedsException = false; 323 if((by & 0x80) != 0x80) { 324 // no continuation - 1 byte branch same in alt and std... 325 if((by == 0x01) && (m_interface->getComponentOpMode() & ETMV3_OPFLG_UNFORMATTED_SOURCE)) 326 { 327 // TBD: need to fix up for handling bypassed ETM stream at some point. 328 throwUnsupportedErr("Bypassed ETM stream not supported in this version of the decoder."); 329 // could be EOTrace marker from bypassed formatter 330 m_curr_packet.SetType(ETM3_PKT_BRANCH_OR_BYPASS_EOT); 331 } 332 else 333 { 334 OnBranchAddress(); 335 SendPacket(); // mark ready to send. 336 } 337 } 338 } 339 // check for p-header - 0b1xxxxxx0 340 else if((by & 0x81) == 0x80) { 341 m_curr_packet.SetType(ETM3_PKT_P_HDR); 342 if(m_curr_packet.UpdateAtomFromPHdr(by,m_config.isCycleAcc())) 343 SendPacket(); 344 else 345 throwPacketHeaderErr("Invalid P-Header."); 346 } 347 // check 0b0000xx00 group 348 else if((by & 0xF3) == 0x00) { 349 350 // A-Sync 351 if(by == 0x00) { 352 m_curr_packet.SetType(ETM3_PKT_A_SYNC); 353 } 354 // cycle count 355 else if(by == 0x04) { 356 m_curr_packet.SetType(ETM3_PKT_CYCLE_COUNT); 357 } 358 // I-Sync 359 else if(by == 0x08) { 360 m_curr_packet.SetType(ETM3_PKT_I_SYNC); 361 m_bIsync_got_cycle_cnt = false; 362 m_bIsync_get_LSiP_addr = false; 363 } 364 // trigger 365 else if(by == 0x0C) { 366 m_curr_packet.SetType(ETM3_PKT_TRIGGER); 367 // no payload - just send it. 368 SendPacket(); 369 } 370 } 371 // check remaining 0bxxxxxx00 codes 372 else if((by & 0x03 )== 0x00) { 373 // OoO data 0b0xx0xx00 374 if((by & 0x93 )== 0x00) { 375 if(!m_config.isDataValTrace()) { 376 m_curr_packet.SetErrType(ETM3_PKT_BAD_TRACEMODE); 377 throwPacketHeaderErr("Invalid data trace header (out of order data) - not tracing data values."); 378 } 379 m_curr_packet.SetType(ETM3_PKT_OOO_DATA); 380 uint8_t size = ((by & 0x0C) >> 2); 381 // header contains a count of the data to follow 382 // size 3 == 4 bytes, other sizes == size bytes 383 if(size == 0) 384 { 385 m_curr_packet.SetDataOOOTag((by >> 5) & 0x3); 386 m_curr_packet.SetDataValue(0); 387 SendPacket(); 388 } 389 else 390 m_bytesExpectedThisPkt = (short)(1 + ((size == 3) ? 4 : size)); 391 } 392 // I-Sync + cycle count 393 else if(by == 0x70) { 394 m_curr_packet.SetType(ETM3_PKT_I_SYNC_CYCLE); 395 m_bIsync_got_cycle_cnt = false; 396 m_bIsync_get_LSiP_addr = false; 397 } 398 // store failed 399 else if(by == 0x50) { 400 if(!m_config.isDataValTrace()) 401 { 402 m_curr_packet.SetErrType(ETM3_PKT_BAD_TRACEMODE); 403 throwPacketHeaderErr("Invalid data trace header (store failed) - not tracing data values."); 404 } 405 m_curr_packet.SetType(ETM3_PKT_STORE_FAIL); 406 SendPacket(); 407 } 408 // OoO placeholder 0b01x1xx00 409 else if((by & 0xD3 )== 0x50) { 410 m_curr_packet.SetType(ETM3_PKT_OOO_ADDR_PLC); 411 if(!m_config.isDataTrace()) 412 { 413 m_curr_packet.SetErrType(ETM3_PKT_BAD_TRACEMODE); 414 throwPacketHeaderErr("Invalid data trace header (out of order placeholder) - not tracing data."); 415 } 416 // expecting data address if flagged and address tracing enabled (flag can be set even if address tracing disabled) 417 m_bExpectingDataAddress = ((by & DATA_ADDR_EXPECTED_FLAG) == DATA_ADDR_EXPECTED_FLAG) && m_config.isDataAddrTrace(); 418 m_bFoundDataAddress = false; 419 m_curr_packet.SetDataOOOTag((by >> 2) & 0x3); 420 if(!m_bExpectingDataAddress) { 421 SendPacket(); 422 } 423 } 424 // vmid 0b00111100 425 else if(by == 0x3c) { 426 m_curr_packet.SetType(ETM3_PKT_VMID); 427 } 428 else 429 { 430 m_curr_packet.SetErrType(ETM3_PKT_RESERVED); 431 throwPacketHeaderErr("Packet header reserved encoding"); 432 } 433 } 434 // normal data 0b00x0xx10 435 else if((by & 0xD3 )== 0x02) { 436 uint8_t size = ((by & 0x0C) >> 2); 437 if(!m_config.isDataTrace()) { 438 m_curr_packet.SetErrType(ETM3_PKT_BAD_TRACEMODE); 439 throwPacketHeaderErr("Invalid data trace header (normal data) - not tracing data."); 440 } 441 m_curr_packet.SetType(ETM3_PKT_NORM_DATA); 442 m_bExpectingDataAddress = ((by & DATA_ADDR_EXPECTED_FLAG) == DATA_ADDR_EXPECTED_FLAG) && m_config.isDataAddrTrace(); 443 m_bFoundDataAddress = false; 444 445 // set this with the data bytes expected this packet, plus the header byte. 446 m_bytesExpectedThisPkt = (short)( 1 + ((size == 3) ? 4 : size)); 447 if(!m_bExpectingDataAddress && (m_bytesExpectedThisPkt == 1)) { 448 // single byte data packet, value = 0; 449 m_curr_packet.SetDataValue(0); 450 SendPacket(); 451 } 452 453 } 454 // data suppressed 0b01100010 455 else if(by == 0x62) { 456 if(!m_config.isDataTrace()) 457 { 458 m_curr_packet.SetErrType(ETM3_PKT_BAD_TRACEMODE); 459 throwPacketHeaderErr("Invalid data trace header (data suppressed) - not tracing data."); 460 } 461 m_curr_packet.SetType(ETM3_PKT_DATA_SUPPRESSED); 462 SendPacket(); 463 } 464 // value not traced 0b011x1010 465 else if((by & 0xEF )== 0x6A) { 466 if(!m_config.isDataTrace()) { 467 m_curr_packet.SetErrType(ETM3_PKT_BAD_TRACEMODE); 468 throwPacketHeaderErr("Invalid data trace header (value not traced) - not tracing data."); 469 } 470 m_curr_packet.SetType(ETM3_PKT_VAL_NOT_TRACED); 471 m_bExpectingDataAddress = ((by & DATA_ADDR_EXPECTED_FLAG) == DATA_ADDR_EXPECTED_FLAG) && m_config.isDataAddrTrace(); 472 m_bFoundDataAddress = false; 473 if(!m_bExpectingDataAddress) { 474 SendPacket(); 475 } 476 } 477 // ignore 0b01100110 478 else if(by == 0x66) { 479 m_curr_packet.SetType(ETM3_PKT_IGNORE); 480 SendPacket(); 481 } 482 // context ID 0b01101110 483 else if(by == 0x6E) { 484 m_curr_packet.SetType(ETM3_PKT_CONTEXT_ID); 485 m_bytesExpectedThisPkt = (short)(1 + m_config.CtxtIDBytes()); 486 } 487 // exception return 0b01110110 488 else if(by == 0x76) { 489 m_curr_packet.SetType(ETM3_PKT_EXCEPTION_EXIT); 490 SendPacket(); 491 } 492 // exception entry 0b01111110 493 else if(by == 0x7E) { 494 m_curr_packet.SetType(ETM3_PKT_EXCEPTION_ENTRY); 495 SendPacket(); 496 } 497 // timestamp packet 0b01000x10 498 else if((by & 0xFB )== 0x42) 499 { 500 m_curr_packet.SetType(ETM3_PKT_TIMESTAMP); 501 } 502 else 503 { 504 m_curr_packet.SetErrType(ETM3_PKT_RESERVED); 505 throwPacketHeaderErr("Packet header reserved encoding."); 506 } 507 return OCSD_OK; 508 } 509 510 ocsd_err_t EtmV3PktProcImpl::processPayloadByte(uint8_t by) 511 { 512 bool bTopBitSet = false; 513 bool packetDone = false; 514 515 // pop byte into buffer 516 m_currPacketData.push_back(by); 517 518 switch(m_curr_packet.getType()) { 519 default: 520 throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_PKT_INTERP_FAIL,m_packet_index,m_chanIDCopy,"Interpreter failed - cannot process payload for unexpected or unsupported packet."); 521 break; 522 523 case ETM3_PKT_BRANCH_ADDRESS: 524 bTopBitSet = (bool)((by & 0x80) == 0x80); 525 if(m_config.isAltBranch()) // etm implements the alternative branch encoding 526 { 527 if(!bTopBitSet) // no continuation 528 { 529 if(!m_BranchPktNeedsException) 530 { 531 if((by & 0xC0) == 0x40) 532 m_BranchPktNeedsException = true; 533 else 534 packetDone = true; 535 } 536 else 537 packetDone = true; 538 } 539 } 540 else 541 { 542 // standard encoding < 5 bytes cannot be exception branch 543 // 5 byte packet 544 if(m_currPacketData.size() == 5) { 545 if((by & 0xC0) == 0x40) 546 // expecting follow up byte(s) 547 m_BranchPktNeedsException = true; 548 else 549 packetDone = true; 550 } 551 // waiting for exception packet 552 else if(m_BranchPktNeedsException){ 553 if(!bTopBitSet) 554 packetDone = true; 555 } 556 else { 557 // not exception - end of packets 558 if(!bTopBitSet) 559 packetDone = true; 560 } 561 } 562 563 if(packetDone) 564 { 565 OnBranchAddress(); 566 SendPacket(); 567 } 568 break; 569 570 case ETM3_PKT_BRANCH_OR_BYPASS_EOT: 571 /* 572 if((by != 0x00) || ( m_currPacketData.size() == ETM3_PKT_BUFF_SIZE)) { 573 if(by == 0x80 && ( m_currPacketData.size() == 7)) { 574 // branch 0 followed by A-sync! 575 m_currPacketData.size() = 1; 576 m_curr_packet.SetType(ETM3_PKT_BRANCH_ADDRESS; 577 SendPacket(); 578 memcpy(m_currPacketData, &m_currPacketData[1],6); 579 m_currPacketData.size() = 6; 580 m_curr_packet.SetType(ETM3_PKT_A_SYNC; 581 SendPacket(); 582 } 583 else if( m_currPacketData.size() == 2) { 584 // branch followed by another byte 585 m_currPacketData.size() = 1; 586 m_curr_packet.SetType(ETM3_PKT_BRANCH_ADDRESS; 587 SendPacket(); 588 ProcessHeaderByte(by); 589 } 590 else if(by == 0x00) { 591 // end of buffer...output something - incomplete / unknown. 592 SendPacket(); 593 } 594 else if(by == 0x01) { 595 // 0x01 - 0x00 x N - 0x1 596 // end of buffer...output something 597 m_currPacketData.size()--; 598 SendPacket(); 599 ProcessHeaderByte(by); 600 } 601 else { 602 // branch followed by unknown sequence 603 int oldidx = m_currPacketData.size(); 604 m_currPacketData.size() = 1; 605 m_curr_packet.SetType(ETM3_PKT_BRANCH_ADDRESS; 606 SendPacket(); 607 oldidx--; 608 memcpy(m_currPacketData, &m_currPacketData[1],oldidx); 609 m_currPacketData.size() = oldidx; 610 SendBadPacket("ERROR : unknown sequence"); 611 } 612 }*/ 613 // just ignore zeros 614 break; 615 616 617 618 case ETM3_PKT_A_SYNC: 619 if(by == 0x00) { 620 if( m_currPacketData.size() > 5) { 621 // extra 0, need to lose one 622 623 // set error type 624 m_curr_packet.SetErrType(ETM3_PKT_BAD_SEQUENCE); 625 // mark extra 0 for sending, retain remaining, restart in A-SYNC processing mode. 626 setBytesPartPkt(1,PROC_DATA,ETM3_PKT_A_SYNC); 627 throwMalformedPacketErr("A-Sync ?: Extra 0x00 in sequence"); 628 } 629 } 630 else if((by == 0x80) && ( m_currPacketData.size() == 6)) { 631 SendPacket(); 632 m_bStreamSync = true; 633 } 634 else 635 { 636 m_curr_packet.SetErrType(ETM3_PKT_BAD_SEQUENCE); 637 m_bytesProcessed--; // remove the last byte from the number processed to re-try 638 m_currPacketData.pop_back(); // remove the last byte processed from the packet 639 throwMalformedPacketErr("A-Sync ? : Unexpected byte in sequence"); 640 } 641 break; 642 643 case ETM3_PKT_CYCLE_COUNT: 644 bTopBitSet = ((by & 0x80) == 0x80); 645 if(!bTopBitSet || ( m_currPacketData.size() >= 6)) { 646 m_currPktIdx = 1; 647 m_curr_packet.SetCycleCount(extractCycleCount()); 648 SendPacket(); 649 } 650 break; 651 652 case ETM3_PKT_I_SYNC_CYCLE: 653 if(!m_bIsync_got_cycle_cnt) { 654 if(((by & 0x80) != 0x80) || ( m_currPacketData.size() >= 6)) { 655 m_bIsync_got_cycle_cnt = true; 656 } 657 break; 658 } 659 // fall through when we have the first non-cycle count byte 660 case ETM3_PKT_I_SYNC: 661 if(m_bytesExpectedThisPkt == 0) { 662 int cycCountBytes = m_currPacketData.size() - 2; 663 int ctxtIDBytes = m_config.CtxtIDBytes(); 664 // bytes expected = header + n x ctxt id + info byte + 4 x addr; 665 if(m_config.isInstrTrace()) 666 m_bytesExpectedThisPkt = cycCountBytes + 6 + ctxtIDBytes; 667 else 668 m_bytesExpectedThisPkt = 2 + ctxtIDBytes; 669 m_IsyncInfoIdx = 1 + cycCountBytes + ctxtIDBytes; 670 } 671 if(( m_currPacketData.size() - 1) == (unsigned)m_IsyncInfoIdx) { 672 m_bIsync_get_LSiP_addr = ((m_currPacketData[m_IsyncInfoIdx] & 0x80) == 0x80); 673 } 674 675 // if bytes collected >= bytes expected 676 if( m_currPacketData.size() >= m_bytesExpectedThisPkt) { 677 // if we still need the LSip Addr, then this is not part of the expected 678 // count as we have no idea how long it is 679 if(m_bIsync_get_LSiP_addr) { 680 if((by & 0x80) != 0x80) { 681 OnISyncPacket(); 682 } 683 } 684 else { 685 // otherwise, output now 686 OnISyncPacket(); 687 } 688 } 689 break; 690 691 case ETM3_PKT_NORM_DATA: 692 if(m_bExpectingDataAddress && !m_bFoundDataAddress) { 693 // look for end of continuation bits 694 if((by & 0x80) != 0x80) { 695 m_bFoundDataAddress = true; 696 // add on the bytes we have found for the address to the expected data bytes 697 m_bytesExpectedThisPkt += ( m_currPacketData.size() - 1); 698 } 699 else 700 break; 701 } 702 // found any data address we were expecting 703 else if(m_bytesExpectedThisPkt == m_currPacketData.size()) { 704 m_currPktIdx = 1; 705 if(m_bExpectingDataAddress) 706 { 707 uint8_t bits = 0, beVal = 0; 708 bool updateBE = false; 709 uint32_t dataAddress = extractDataAddress(bits,updateBE,beVal); 710 m_curr_packet.UpdateDataAddress(dataAddress, bits); 711 if(updateBE) 712 m_curr_packet.UpdateDataEndian(beVal); 713 } 714 m_curr_packet.SetDataValue(extractDataValue((m_currPacketData[0] >> 2) & 0x3)); 715 SendPacket(); 716 } 717 break; 718 719 case ETM3_PKT_OOO_DATA: 720 if(m_bytesExpectedThisPkt == m_currPacketData.size()) 721 { 722 m_currPktIdx = 1; 723 m_curr_packet.SetDataValue(extractDataValue((m_currPacketData[0] >> 2) & 0x3)); 724 m_curr_packet.SetDataOOOTag((m_currPacketData[0] >> 5) & 0x3); 725 SendPacket(); 726 } 727 if(m_bytesExpectedThisPkt < m_currPacketData.size()) 728 throwMalformedPacketErr("Malformed out of order data packet."); 729 break; 730 731 // both these expect an address only. 732 case ETM3_PKT_VAL_NOT_TRACED: 733 case ETM3_PKT_OOO_ADDR_PLC: // we set the tag earlier. 734 if(m_bExpectingDataAddress) { 735 // look for end of continuation bits 736 if((by & 0x80) != 0x80) { 737 uint8_t bits = 0, beVal = 0; 738 bool updateBE = false; 739 m_currPktIdx = 1; 740 uint32_t dataAddress = extractDataAddress(bits,updateBE,beVal); 741 m_curr_packet.UpdateDataAddress(dataAddress, bits); 742 if(updateBE) 743 m_curr_packet.UpdateDataEndian(beVal); 744 SendPacket(); 745 } 746 } 747 break; 748 749 case ETM3_PKT_CONTEXT_ID: 750 if(m_bytesExpectedThisPkt == m_currPacketData.size()) { 751 m_currPktIdx = 1; 752 m_curr_packet.UpdateContextID(extractCtxtID()); 753 SendPacket(); 754 } 755 if(m_bytesExpectedThisPkt < m_currPacketData.size()) 756 throwMalformedPacketErr("Malformed context id packet."); 757 break; 758 759 case ETM3_PKT_TIMESTAMP: 760 if((by & 0x80) != 0x80) { 761 uint8_t tsBits = 0; 762 m_currPktIdx = 1; 763 uint64_t tsVal = extractTimestamp(tsBits); 764 m_curr_packet.UpdateTimestamp(tsVal,tsBits); 765 SendPacket(); 766 } 767 break; 768 769 case ETM3_PKT_VMID: 770 // single byte payload 771 m_curr_packet.UpdateVMID(by); 772 SendPacket(); 773 break; 774 } 775 776 return OCSD_OK; 777 } 778 779 // extract branch address packet at current location in packet data. 780 void EtmV3PktProcImpl::OnBranchAddress() 781 { 782 int validBits = 0; 783 ocsd_vaddr_t partAddr = 0; 784 785 partAddr = extractBrAddrPkt(validBits); 786 m_curr_packet.UpdateAddress(partAddr,validBits); 787 } 788 789 uint32_t EtmV3PktProcImpl::extractBrAddrPkt(int &nBitsOut) 790 { 791 static int addrshift[] = { 792 2, // ARM_ISA 793 1, // thumb 794 1, // thumb EE 795 0 // jazelle 796 }; 797 798 static uint8_t addrMask[] = { // byte 5 masks 799 0x7, // ARM_ISA 800 0xF, // thumb 801 0xF, // thumb EE 802 0x1F // jazelle 803 }; 804 805 static int addrBits[] = { // address bits in byte 5 806 3, // ARM_ISA 807 4, // thumb 808 4, // thumb EE 809 5 // jazelle 810 }; 811 812 static ocsd_armv7_exception exceptionTypeARMdeprecated[] = { 813 Excp_Reset, 814 Excp_IRQ, 815 Excp_Reserved, 816 Excp_Reserved, 817 Excp_Jazelle, 818 Excp_FIQ, 819 Excp_AsyncDAbort, 820 Excp_DebugHalt 821 }; 822 823 bool CBit = true; 824 int bytecount = 0; 825 int bitcount = 0; 826 int shift = 0; 827 int isa_idx = 0; 828 uint32_t value = 0; 829 uint8_t addrbyte; 830 bool byte5AddrUpdate = false; 831 832 while(CBit && bytecount < 4) 833 { 834 checkPktLimits(); 835 addrbyte = m_currPacketData[m_currPktIdx++]; 836 CBit = (bool)((addrbyte & 0x80) != 0); 837 shift = bitcount; 838 if(bytecount == 0) 839 { 840 addrbyte &= ~0x81; 841 bitcount+=6; 842 addrbyte >>= 1; 843 } 844 else 845 { 846 // bytes 2-4, no continuation, alt format uses bit 6 to indicate following exception bytes 847 if(m_config.isAltBranch() && !CBit) 848 { 849 // last compressed address byte with exception 850 if((addrbyte & 0x40) == 0x40) 851 extractExceptionData(); 852 addrbyte &= 0x3F; 853 bitcount+=6; 854 } 855 else 856 { 857 addrbyte &= 0x7F; 858 bitcount+=7; 859 } 860 } 861 value |= ((uint32_t)addrbyte) << shift; 862 bytecount++; 863 } 864 865 // byte 5 - indicates following exception bytes (or not!) 866 if(CBit) 867 { 868 checkPktLimits(); 869 addrbyte = m_currPacketData[m_currPktIdx++]; 870 871 // deprecated original byte 5 encoding - ARM state exception only 872 if(addrbyte & 0x80) 873 { 874 uint8_t excep_num = (addrbyte >> 3) & 0x7; 875 m_curr_packet.UpdateISA(ocsd_isa_arm); 876 m_curr_packet.SetException(exceptionTypeARMdeprecated[excep_num], excep_num, (addrbyte & 0x40) ? true : false,m_config.isV7MArch()); 877 } 878 else 879 // normal 5 byte branch, or uses exception bytes. 880 { 881 // go grab the exception bits to correctly interpret the ISA state 882 if((addrbyte & 0x40) == 0x40) 883 extractExceptionData(); 884 885 if((addrbyte & 0xB8) == 0x08) 886 m_curr_packet.UpdateISA(ocsd_isa_arm); 887 else if ((addrbyte & 0xB0) == 0x10) 888 m_curr_packet.UpdateISA(m_curr_packet.AltISA() ? ocsd_isa_tee : ocsd_isa_thumb2); 889 else if ((addrbyte & 0xA0) == 0x20) 890 m_curr_packet.UpdateISA(ocsd_isa_jazelle); 891 else 892 throwMalformedPacketErr("Malformed Packet - Unknown ISA."); 893 } 894 895 byte5AddrUpdate = true; // need to update the address value from byte 5 896 } 897 898 // figure out the correct ISA shifts for the address bits 899 switch(m_curr_packet.ISA()) 900 { 901 case ocsd_isa_thumb2: isa_idx = 1; break; 902 case ocsd_isa_tee: isa_idx = 2; break; 903 case ocsd_isa_jazelle: isa_idx = 3; break; 904 default: break; 905 } 906 907 if(byte5AddrUpdate) 908 { 909 value |= ((uint32_t)(addrbyte & addrMask[isa_idx])) << bitcount; 910 bitcount += addrBits[isa_idx]; 911 } 912 913 // finally align according to ISA 914 shift = addrshift[isa_idx]; 915 value <<= shift; 916 bitcount += shift; 917 918 nBitsOut = bitcount; 919 return value; 920 } 921 922 // extract exception data from bytes after address. 923 void EtmV3PktProcImpl::extractExceptionData() 924 { 925 static const ocsd_armv7_exception exceptionTypesStd[] = { 926 Excp_NoException, Excp_DebugHalt, Excp_SMC, Excp_Hyp, 927 Excp_AsyncDAbort, Excp_Jazelle, Excp_Reserved, Excp_Reserved, 928 Excp_Reset, Excp_Undef, Excp_SVC, Excp_PrefAbort, 929 Excp_SyncDataAbort, Excp_Generic, Excp_IRQ, Excp_FIQ 930 }; 931 932 static const ocsd_armv7_exception exceptionTypesCM[] = { 933 Excp_NoException, Excp_CMIRQn, Excp_CMIRQn, Excp_CMIRQn, 934 Excp_CMIRQn, Excp_CMIRQn, Excp_CMIRQn, Excp_CMIRQn, 935 Excp_CMIRQn, Excp_CMUsageFault, Excp_CMNMI, Excp_SVC, 936 Excp_CMDebugMonitor, Excp_CMMemManage, Excp_CMPendSV, Excp_CMSysTick, 937 Excp_Reserved, Excp_Reset, Excp_Reserved, Excp_CMHardFault, 938 Excp_Reserved, Excp_CMBusFault, Excp_Reserved, Excp_Reserved 939 }; 940 941 uint16_t exceptionNum = 0; 942 ocsd_armv7_exception excep_type = Excp_Reserved; 943 int resume = 0; 944 int irq_n = 0; 945 bool cancel_prev_instr = 0; 946 bool Byte2 = false; 947 948 checkPktLimits(); 949 950 //**** exception info Byte 0 951 uint8_t dataByte = m_currPacketData[m_currPktIdx++]; 952 953 m_curr_packet.UpdateNS(dataByte & 0x1); 954 exceptionNum |= (dataByte >> 1) & 0xF; 955 cancel_prev_instr = (dataByte & 0x20) ? true : false; 956 m_curr_packet.UpdateAltISA(((dataByte & 0x40) != 0) ? 1 : 0); 957 958 //** another byte? 959 if(dataByte & 0x80) 960 { 961 checkPktLimits(); 962 dataByte = m_currPacketData[m_currPktIdx++]; 963 964 if(dataByte & 0x40) 965 Byte2 = true; //** immediate info byte 2, skipping 1 966 else 967 { 968 //**** exception info Byte 1 969 if(m_config.isV7MArch()) 970 { 971 exceptionNum |= ((uint16_t)(dataByte & 0x1F)) << 4; 972 } 973 m_curr_packet.UpdateHyp(dataByte & 0x20 ? 1 : 0); 974 975 if(dataByte & 0x80) 976 { 977 checkPktLimits(); 978 dataByte = m_currPacketData[m_currPktIdx++]; 979 Byte2 = true; 980 } 981 } 982 //**** exception info Byte 2 983 if(Byte2) 984 { 985 resume = dataByte & 0xF; 986 } 987 } 988 989 // set the exception type - according to the number and core profile 990 if(m_config.isV7MArch()) 991 { 992 exceptionNum &= 0x1FF; 993 if(exceptionNum < 0x018) 994 excep_type= exceptionTypesCM[exceptionNum]; 995 else 996 excep_type = Excp_CMIRQn; 997 998 if(excep_type == Excp_CMIRQn) 999 { 1000 if(exceptionNum > 0x018) 1001 irq_n = exceptionNum - 0x10; 1002 else if(exceptionNum == 0x008) 1003 irq_n = 0; 1004 else 1005 irq_n = exceptionNum; 1006 } 1007 } 1008 else 1009 { 1010 exceptionNum &= 0xF; 1011 excep_type = exceptionTypesStd[exceptionNum]; 1012 } 1013 m_curr_packet.SetException(excep_type, exceptionNum, cancel_prev_instr,m_config.isV7MArch(), irq_n,resume); 1014 } 1015 1016 void EtmV3PktProcImpl::checkPktLimits() 1017 { 1018 // index running off the end of the packet means a malformed packet. 1019 if(m_currPktIdx >= m_currPacketData.size()) 1020 throwMalformedPacketErr("Malformed Packet - oversized packet."); 1021 } 1022 1023 uint32_t EtmV3PktProcImpl::extractCtxtID() 1024 { 1025 uint32_t ctxtID = 0; 1026 int size = m_config.CtxtIDBytes(); 1027 1028 // check we have enough data 1029 if((m_currPktIdx + size) > m_currPacketData.size()) 1030 throwMalformedPacketErr("Too few bytes to extract context ID."); 1031 1032 switch(size) 1033 { 1034 case 1: 1035 ctxtID = (uint32_t)m_currPacketData[m_currPktIdx]; 1036 m_currPktIdx++; 1037 break; 1038 1039 case 2: 1040 ctxtID = (uint32_t)m_currPacketData[m_currPktIdx] 1041 | ((uint32_t)m_currPacketData[m_currPktIdx+1]) << 8; 1042 m_currPktIdx+=2; 1043 break; 1044 1045 case 4: 1046 ctxtID = (uint32_t)m_currPacketData[m_currPktIdx] 1047 | ((uint32_t)m_currPacketData[m_currPktIdx+1]) << 8 1048 | ((uint32_t)m_currPacketData[m_currPktIdx+2]) << 16 1049 | ((uint32_t)m_currPacketData[m_currPktIdx+3]) << 24; 1050 m_currPktIdx+=4; 1051 break; 1052 } 1053 return ctxtID; 1054 } 1055 1056 uint64_t EtmV3PktProcImpl::extractTimestamp(uint8_t &tsBits) 1057 { 1058 uint64_t ts = 0; 1059 unsigned tsMaxBytes = m_config.TSPkt64() ? 9 : 7; 1060 unsigned tsCurrBytes = 0; 1061 bool bCont = true; 1062 uint8_t mask = 0x7F; 1063 uint8_t last_mask = m_config.TSPkt64() ? 0xFF : 0x3F; 1064 uint8_t ts_iter_bits = 7; 1065 uint8_t ts_last_iter_bits = m_config.TSPkt64() ? 8 : 6; 1066 uint8_t currByte; 1067 tsBits = 0; 1068 1069 while((tsCurrBytes < tsMaxBytes) && bCont) 1070 { 1071 if(m_currPacketData.size() < (m_currPktIdx + tsCurrBytes + 1)) 1072 throwMalformedPacketErr("Insufficient bytes to extract timestamp."); 1073 1074 currByte = m_currPacketData[m_currPktIdx+tsCurrBytes]; 1075 ts |= ((uint64_t)(currByte & mask)) << (7 * tsCurrBytes); 1076 tsCurrBytes++; 1077 tsBits += ts_iter_bits; 1078 bCont = ((0x80 & currByte) == 0x80); 1079 if(tsCurrBytes == (tsMaxBytes - 1)) 1080 { 1081 mask = last_mask; 1082 ts_iter_bits = ts_last_iter_bits; 1083 } 1084 } 1085 m_currPktIdx += tsCurrBytes; 1086 return ts; 1087 } 1088 1089 1090 uint32_t EtmV3PktProcImpl::extractDataAddress(uint8_t &bits, bool &updateBE, uint8_t &beVal) 1091 { 1092 uint32_t dataAddr = 0; 1093 int bytesIdx = 0; 1094 bool bCont = true; 1095 uint8_t currByte = 0; 1096 1097 updateBE = false; 1098 bits = 0; 1099 1100 while(bCont) 1101 { 1102 checkPktLimits(); 1103 currByte = m_currPacketData[m_currPktIdx++] & ((bytesIdx == 4) ? 0x0F : 0x7F); 1104 dataAddr |= (((uint32_t)currByte) << (bytesIdx * 7)); 1105 bCont = ((currByte & 0x80) == 0x80); 1106 if(bytesIdx == 4) 1107 { 1108 bits += 4; 1109 updateBE = true; 1110 beVal = ((currByte >> 4) & 0x1); 1111 bCont = false; 1112 } 1113 else 1114 bits+=7; 1115 bytesIdx++; 1116 } 1117 return dataAddr; 1118 } 1119 1120 uint32_t EtmV3PktProcImpl::extractDataValue(const int dataByteSize) 1121 { 1122 static int bytesReqTable[] = { 0,1,2,4 }; 1123 1124 uint32_t dataVal = 0; 1125 int bytesUsed = 0; 1126 int bytesReq = bytesReqTable[dataByteSize & 0x3]; 1127 while(bytesUsed < bytesReq) 1128 { 1129 checkPktLimits(); 1130 dataVal |= (((uint32_t)m_currPacketData[m_currPktIdx++]) << (bytesUsed * 8)); 1131 bytesUsed++; 1132 } 1133 return dataVal; 1134 } 1135 1136 1137 uint32_t EtmV3PktProcImpl::extractCycleCount() 1138 { 1139 uint32_t cycleCount = 0; 1140 int byteIdx = 0; 1141 uint8_t mask = 0x7F; 1142 bool bCond = true; 1143 uint8_t currByte = 0; 1144 1145 while(bCond) 1146 { 1147 checkPktLimits(); 1148 currByte = m_currPacketData[m_currPktIdx++]; 1149 cycleCount |= ((uint32_t)(currByte & mask)) << (7 * byteIdx); 1150 bCond = ((currByte & 0x80) == 0x80); 1151 byteIdx++; 1152 1153 if(byteIdx == 4) 1154 mask = 0x0F; 1155 1156 if(byteIdx == 5) 1157 bCond = false; 1158 } 1159 return cycleCount; 1160 } 1161 1162 void EtmV3PktProcImpl::OnISyncPacket() 1163 { 1164 uint8_t iSyncInfoByte = 0; 1165 uint32_t instrAddr = 0, LSiPAddr = 0; 1166 int LSiPBits = 0; 1167 uint8_t T = 0, J = 0, AltISA = 0; 1168 1169 m_currPktIdx = 1; 1170 if(m_bIsync_got_cycle_cnt) 1171 { 1172 m_curr_packet.SetCycleCount(extractCycleCount()); 1173 m_curr_packet.SetISyncHasCC(); 1174 } 1175 1176 if(m_config.CtxtIDBytes() != 0) 1177 { 1178 m_curr_packet.UpdateContextID(extractCtxtID()); 1179 } 1180 1181 // extract context info 1182 iSyncInfoByte = m_currPacketData[m_currPktIdx++]; 1183 m_curr_packet.SetISyncReason((ocsd_iSync_reason)((iSyncInfoByte >> 5) & 0x3)); 1184 J = (iSyncInfoByte >> 4) & 0x1; 1185 AltISA = m_config.MinorRev() >= 3 ? (iSyncInfoByte >> 2) & 0x1 : 0; 1186 m_curr_packet.UpdateNS((iSyncInfoByte >> 3) & 0x1); 1187 if(m_config.hasVirtExt()) 1188 m_curr_packet.UpdateHyp((iSyncInfoByte >> 1) & 0x1); 1189 1190 // main address value - full 32 bit address value 1191 if(m_config.isInstrTrace()) 1192 { 1193 for(int i = 0; i < 4; i++) 1194 instrAddr |= ((uint32_t)m_currPacketData[m_currPktIdx++]) << (8*i); 1195 T = instrAddr & 0x1; // get the T bit. 1196 instrAddr &= ~0x1; // remove from address. 1197 m_curr_packet.UpdateAddress(instrAddr,32); 1198 1199 // enough data now to set the instruction set. 1200 ocsd_isa currISA = ocsd_isa_arm; 1201 if(J) 1202 currISA = ocsd_isa_jazelle; 1203 else if(T) 1204 currISA = AltISA ? ocsd_isa_tee : ocsd_isa_thumb2; 1205 m_curr_packet.UpdateISA(currISA); 1206 1207 // possible follow up address value - rarely uses unless trace enabled during 1208 // load and store instruction executing on top of other instruction. 1209 if(m_bIsync_get_LSiP_addr) 1210 { 1211 LSiPAddr = extractBrAddrPkt(LSiPBits); 1212 // follow up address value is compressed relative to the main value 1213 // we store this in the data address value temporarily. 1214 m_curr_packet.UpdateDataAddress(instrAddr,32); 1215 m_curr_packet.UpdateDataAddress(LSiPAddr,LSiPBits); 1216 } 1217 } 1218 else 1219 m_curr_packet.SetISyncNoAddr(); 1220 1221 SendPacket(); // mark ready to send 1222 } 1223 1224 /* End of File trc_pkt_proc_etmv3_impl.cpp */ 1225