1 /* 2 * \file trc_pkt_elem_ptm.cpp 3 * \brief OpenCSD : 4 * 5 * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. 6 */ 7 8 9 /* 10 * Redistribution and use in source and binary forms, with or without modification, 11 * are permitted provided that the following conditions are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright notice, 14 * this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright notice, 17 * this list of conditions and the following disclaimer in the documentation 18 * and/or other materials provided with the distribution. 19 * 20 * 3. Neither the name of the copyright holder nor the names of its contributors 21 * may be used to endorse or promote products derived from this software without 22 * specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 28 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 #include <sstream> 37 #include <iomanip> 38 39 #include "opencsd/ptm/trc_pkt_elem_ptm.h" 40 41 PtmTrcPacket::PtmTrcPacket() 42 { 43 } 44 45 PtmTrcPacket::~PtmTrcPacket() 46 { 47 } 48 49 PtmTrcPacket &PtmTrcPacket::operator =(const ocsd_ptm_pkt* p_pkt) 50 { 51 *dynamic_cast<ocsd_ptm_pkt *>(this) = *p_pkt; 52 return *this; 53 } 54 55 void PtmTrcPacket::Clear() 56 { 57 err_type = PTM_PKT_NOERROR; 58 cycle_count = 0; 59 cc_valid = 0; 60 context.updated = 0; 61 context.updated_c = 0; 62 context.updated_v = 0; 63 ts_update_bits = 0; 64 atom.En_bits = 0; 65 exception.bits.present = 0; 66 prev_isa = curr_isa; // mark ISA as not changed 67 } 68 69 void PtmTrcPacket::ResetState() 70 { 71 type = PTM_PKT_NOTSYNC; 72 73 context.ctxtID = 0; 74 context.VMID = 0; 75 context.curr_alt_isa = 0; 76 context.curr_Hyp = 0; 77 context.curr_NS = 0; 78 79 addr.valid_bits = 0; 80 addr.size = VA_32BIT; 81 addr.val = 0; 82 83 prev_isa = curr_isa = ocsd_isa_unknown; 84 85 timestamp = 0; 86 87 Clear(); 88 } 89 90 void PtmTrcPacket::UpdateAddress(const ocsd_vaddr_t partAddrVal, const int updateBits) 91 { 92 ocsd_vaddr_t validMask = OCSD_VA_MASK; 93 validMask >>= OCSD_MAX_VA_BITSIZE-updateBits; 94 addr.pkt_bits = updateBits; 95 addr.val &= ~validMask; 96 addr.val |= (partAddrVal & validMask); 97 if(updateBits > addr.valid_bits) 98 addr.valid_bits = updateBits; 99 } 100 101 void PtmTrcPacket::UpdateTimestamp(const uint64_t tsVal, const uint8_t updateBits) 102 { 103 uint64_t validMask = ~0ULL; 104 validMask >>= 64-updateBits; 105 timestamp &= ~validMask; 106 timestamp |= (tsVal & validMask); 107 ts_update_bits = updateBits; 108 } 109 110 void PtmTrcPacket::SetCycleAccAtomFromPHdr(const uint8_t pHdr) 111 { 112 atom.num = 1; 113 atom.En_bits = (pHdr & 0x2) ? 0x0 : 0x1; 114 } 115 116 void PtmTrcPacket::SetAtomFromPHdr(const uint8_t pHdr) 117 { 118 // how many atoms 119 uint8_t atom_fmt_id = pHdr & 0xF0; 120 if(atom_fmt_id == 0x80) 121 { 122 // format 1 or 2 123 if((pHdr & 0x08) == 0x08) 124 atom.num = 2; 125 else 126 atom.num = 1; 127 } 128 else if(atom_fmt_id == 0x90) 129 { 130 atom.num = 3; 131 } 132 else 133 { 134 if((pHdr & 0xE0) == 0xA0) 135 atom.num = 4; 136 else 137 atom.num = 5; 138 } 139 140 // extract the E/N bits 141 uint8_t atom_mask = 0x2; // start @ bit 1 - newest instruction 142 atom.En_bits = 0; 143 for(int i = 0; i < atom.num; i++) 144 { 145 atom.En_bits <<= 1; 146 if(!(atom_mask & pHdr)) // 0 bit is an E in PTM -> a one in the standard atom bit type 147 atom.En_bits |= 0x1; 148 atom_mask <<= 1; 149 } 150 } 151 152 // printing 153 void PtmTrcPacket::toString(std::string &str) const 154 { 155 std::string temp1, temp2; 156 std::ostringstream oss; 157 158 packetTypeName(type, temp1,temp2); 159 oss << temp1 << " : " << temp2 << "; "; 160 161 // some packets require additional data. 162 switch(type) 163 { 164 case PTM_PKT_BAD_SEQUENCE: 165 packetTypeName(err_type, temp1,temp2); 166 oss << "[" << temp1 << "]; "; 167 break; 168 169 case PTM_PKT_ATOM: 170 getAtomStr(temp1); 171 oss << temp1; 172 break; 173 174 case PTM_PKT_CONTEXT_ID: 175 oss << "CtxtID=0x" << std::hex << std::setw(8) << std::setfill('0') << context.ctxtID << "; "; 176 break; 177 178 case PTM_PKT_VMID: 179 oss << "VMID=0x" << std::hex << std::setw(2) << std::setfill('0') << context.VMID << "; "; 180 break; 181 182 case PTM_PKT_WPOINT_UPDATE: 183 case PTM_PKT_BRANCH_ADDRESS: 184 getBranchAddressStr(temp1); 185 oss << temp1; 186 break; 187 188 case PTM_PKT_I_SYNC: 189 getISyncStr(temp1); 190 oss << temp1; 191 break; 192 193 case PTM_PKT_TIMESTAMP: 194 getTSStr(temp1); 195 oss << temp1; 196 break; 197 } 198 199 str = oss.str(); 200 } 201 202 void PtmTrcPacket::toStringFmt(const uint32_t fmtFlags, std::string &str) const 203 { 204 toString(str); 205 } 206 207 void PtmTrcPacket::getAtomStr(std::string &valStr) const 208 { 209 std::ostringstream oss; 210 uint32_t bitpattern = atom.En_bits; // arranged LSBit oldest, MSbit newest 211 212 if(cc_valid) // cycle accurate trace - single atom 213 { 214 std::string subStr; 215 oss << ((bitpattern & 0x1) ? "E" : "N"); // in spec read L->R, oldest->newest 216 oss << "; "; 217 getCycleCountStr(subStr); 218 oss << subStr; 219 } 220 else 221 { 222 // none cycle count 223 for(int i = 0; i < atom.num; i++) 224 { 225 oss << ((bitpattern & 0x1) ? "E" : "N"); // in spec read L->R, oldest->newest 226 bitpattern >>= 1; 227 } 228 oss << "; "; 229 } 230 valStr = oss.str(); 231 } 232 233 void PtmTrcPacket::getBranchAddressStr(std::string &valStr) const 234 { 235 std::ostringstream oss; 236 std::string subStr; 237 238 // print address. 239 trcPrintableElem::getValStr(subStr,32,addr.valid_bits,addr.val,true,addr.pkt_bits); 240 oss << "Addr=" << subStr << "; "; 241 242 // current ISA if changed. 243 if(curr_isa != prev_isa) 244 { 245 getISAStr(subStr); 246 oss << subStr; 247 } 248 249 // S / NS etc if changed. 250 if(context.updated) 251 { 252 oss << (context.curr_NS ? "NS; " : "S; "); 253 oss << (context.curr_Hyp ? "Hyp; " : ""); 254 } 255 256 // exception? 257 if(exception.bits.present) 258 { 259 getExcepStr(subStr); 260 oss << subStr; 261 } 262 263 if(cc_valid) 264 { 265 getCycleCountStr(subStr); 266 oss << subStr; 267 } 268 valStr = oss.str(); 269 } 270 271 void PtmTrcPacket::getISAStr(std::string &isaStr) const 272 { 273 std::ostringstream oss; 274 oss << "ISA="; 275 switch(curr_isa) 276 { 277 case ocsd_isa_arm: 278 oss << "ARM(32); "; 279 break; 280 281 case ocsd_isa_thumb2: 282 oss << "Thumb2; "; 283 break; 284 285 case ocsd_isa_aarch64: 286 oss << "AArch64; "; 287 break; 288 289 case ocsd_isa_tee: 290 oss << "ThumbEE; "; 291 break; 292 293 case ocsd_isa_jazelle: 294 oss << "Jazelle; "; 295 break; 296 297 default: 298 case ocsd_isa_unknown: 299 oss << "Unknown; "; 300 break; 301 } 302 isaStr = oss.str(); 303 } 304 305 void PtmTrcPacket::getExcepStr(std::string &excepStr) const 306 { 307 static const char *ARv7Excep[] = { 308 "No Exception", "Debug Halt", "SMC", "Hyp", 309 "Async Data Abort", "Jazelle", "Reserved", "Reserved", 310 "PE Reset", "Undefined Instr", "SVC", "Prefetch Abort", 311 "Data Fault", "Generic", "IRQ", "FIQ" 312 }; 313 314 std::ostringstream oss; 315 oss << "Excep="; 316 if(exception.number < 16) 317 oss << ARv7Excep[exception.number]; 318 else 319 oss << "Unknown"; 320 oss << " [" << std::hex << std::setw(2) << std::setfill('0') << exception.number << "]; "; 321 excepStr = oss.str(); 322 } 323 324 void PtmTrcPacket::getISyncStr(std::string &valStr) const 325 { 326 std::ostringstream oss; 327 std::string tmpStr; 328 static const char *reason[] = { "Periodic", "Trace Enable", "Restart Overflow", "Debug Exit" }; 329 330 // reason. 331 oss << "(" << reason[(int)i_sync_reason] << "); "; 332 333 // full address. 334 oss << "Addr=0x" << std::hex << std::setfill('0') << std::setw(8) << (uint32_t)addr.val << "; "; 335 336 oss << (context.curr_NS ? "NS; " : "S; "); 337 oss << (context.curr_Hyp ? "Hyp; " : " "); 338 339 if(context.updated_c) 340 { 341 oss << "CtxtID=" << std::hex << std::setw(8) << std::setfill('0') << context.ctxtID << "; "; 342 } 343 344 getISAStr(tmpStr); 345 oss << tmpStr; 346 347 if(cc_valid) 348 { 349 getCycleCountStr(tmpStr); 350 oss << tmpStr; 351 } 352 valStr = oss.str(); 353 } 354 355 void PtmTrcPacket::getTSStr(std::string &valStr) const 356 { 357 std::string tmpStr; 358 std::ostringstream oss; 359 360 trcPrintableElem::getValStr(tmpStr,64,64,timestamp,true,ts_update_bits); 361 oss << "TS=" << tmpStr + "(" << std::dec << timestamp << "); "; 362 if(cc_valid) 363 { 364 getCycleCountStr(tmpStr); 365 oss << tmpStr; 366 } 367 valStr = oss.str(); 368 } 369 370 371 void PtmTrcPacket::getCycleCountStr(std::string &subStr) const 372 { 373 std::ostringstream oss; 374 oss << "Cycles=" << std::dec << cycle_count << "; "; 375 subStr = oss.str(); 376 } 377 378 379 void PtmTrcPacket::packetTypeName(const ocsd_ptm_pkt_type pkt_type, std::string &name, std::string &desc) const 380 { 381 switch(pkt_type) 382 { 383 case PTM_PKT_NOTSYNC: //!< no sync found yet 384 name = "NOTSYNC"; 385 desc = "PTM Not Synchronised"; 386 break; 387 388 case PTM_PKT_INCOMPLETE_EOT: 389 name = "INCOMPLETE_EOT"; 390 desc = "Incomplete packet flushed at end of trace"; 391 break; 392 393 case PTM_PKT_NOERROR: 394 name = "NO_ERROR"; 395 desc = "Error type not set"; 396 break; 397 398 case PTM_PKT_BAD_SEQUENCE: 399 name = "BAD_SEQUENCE"; 400 desc = "Invalid sequence in packet"; 401 break; 402 403 case PTM_PKT_RESERVED: 404 name = "RESERVED"; 405 desc = "Reserved Packet Header"; 406 break; 407 408 case PTM_PKT_BRANCH_ADDRESS: 409 name = "BRANCH_ADDRESS"; 410 desc = "Branch address packet"; 411 break; 412 413 case PTM_PKT_A_SYNC: 414 name = "ASYNC"; 415 desc = "Alignment Synchronisation Packet"; 416 break; 417 418 case PTM_PKT_I_SYNC: 419 name = "ISYNC"; 420 desc = "Instruction Synchronisation packet"; 421 break; 422 423 case PTM_PKT_TRIGGER: 424 name = "TRIGGER"; 425 desc = "Trigger Event packet"; 426 break; 427 428 case PTM_PKT_WPOINT_UPDATE: 429 name = "WP_UPDATE"; 430 desc = "Waypoint update packet"; 431 break; 432 433 case PTM_PKT_IGNORE: 434 name = "IGNORE"; 435 desc = "Ignore packet"; 436 break; 437 438 case PTM_PKT_CONTEXT_ID: 439 name = "CTXTID"; 440 desc = "Context ID packet"; 441 break; 442 443 case PTM_PKT_VMID: 444 name = "VMID"; 445 desc = "VM ID packet"; 446 break; 447 448 case PTM_PKT_ATOM: 449 name = "ATOM"; 450 desc = "Atom packet"; 451 break; 452 453 case PTM_PKT_TIMESTAMP: 454 name = "TIMESTAMP"; 455 desc = "Timestamp packet"; 456 break; 457 458 case PTM_PKT_EXCEPTION_RET: 459 name = "ERET"; 460 desc = "Exception return packet"; 461 break; 462 463 default: 464 name = "UNKNOWN"; 465 desc = "Unknown packet type"; 466 break; 467 468 //PTM_PKT_BRANCH_OR_BYPASS_EOT, 469 //PTM_PKT_TPIU_PAD_EOB, 470 } 471 } 472 473 /* End of File trc_pkt_elem_ptm.cpp */ 474