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
PtmTrcPacket()41 PtmTrcPacket::PtmTrcPacket()
42 {
43 }
44
~PtmTrcPacket()45 PtmTrcPacket::~PtmTrcPacket()
46 {
47 }
48
operator =(const ocsd_ptm_pkt * p_pkt)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
Clear()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
ResetState()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
UpdateAddress(const ocsd_vaddr_t partAddrVal,const int updateBits)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
UpdateTimestamp(const uint64_t tsVal,const uint8_t updateBits)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
SetCycleAccAtomFromPHdr(const uint8_t pHdr)110 void PtmTrcPacket::SetCycleAccAtomFromPHdr(const uint8_t pHdr)
111 {
112 atom.num = 1;
113 atom.En_bits = (pHdr & 0x2) ? 0x0 : 0x1;
114 }
115
SetAtomFromPHdr(const uint8_t pHdr)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
toString(std::string & str) const153 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
toStringFmt(const uint32_t fmtFlags,std::string & str) const202 void PtmTrcPacket::toStringFmt(const uint32_t fmtFlags, std::string &str) const
203 {
204 toString(str);
205 }
206
getAtomStr(std::string & valStr) const207 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
getBranchAddressStr(std::string & valStr) const233 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
getISAStr(std::string & isaStr) const271 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
getExcepStr(std::string & excepStr) const305 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
getISyncStr(std::string & valStr) const324 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
getTSStr(std::string & valStr) const355 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
getCycleCountStr(std::string & subStr) const371 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
packetTypeName(const ocsd_ptm_pkt_type pkt_type,std::string & name,std::string & desc) const379 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