1 /*
2  * \file       trc_pkt_elem_etmv4i.h
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 #ifndef ARM_TRC_PKT_ELEM_ETMV4I_H_INCLUDED
37 #define ARM_TRC_PKT_ELEM_ETMV4I_H_INCLUDED
38 
39 #include "trc_pkt_types_etmv4.h"
40 #include "common/trc_printable_elem.h"
41 #include "common/trc_pkt_elem_base.h"
42 
43 /** @addtogroup trc_pkts
44 @{*/
45 
46 /*!
47 * @class Etmv4PktAddrStack
48 * @brief ETMv4 Address packet values stack
49 * @ingroup trc_pkts
50 *
51 *  This class represents a stack of recent broadcast address values -
52 *  used to fulfil the ExactMatch address type where no address is output.
53 *
54 */
55 class Etmv4PktAddrStack
56 {
57 public:
58     Etmv4PktAddrStack()
59     {
60         for (int i = 0; i < 3; i++)
61         {
62             m_v_addr[i].pkt_bits = 0;
63             m_v_addr[i].size = VA_64BIT;
64             m_v_addr[i].val = 0;
65             m_v_addr[i].valid_bits = 0;
66             m_v_addr_ISA[i] = 0;
67         }
68     }
69     ~Etmv4PktAddrStack() {};
70 
71     void push(const ocsd_pkt_vaddr vaddr, const uint8_t isa)
72     {
73         m_v_addr[2] = m_v_addr[1];
74         m_v_addr[1] = m_v_addr[0];
75         m_v_addr[0] = vaddr;
76         m_v_addr_ISA[2] = m_v_addr_ISA[1];
77         m_v_addr_ISA[1] = m_v_addr_ISA[0];
78         m_v_addr_ISA[0] = isa;
79     }
80 
81     void get_idx(const uint8_t idx, ocsd_pkt_vaddr &vaddr, uint8_t &isa)
82     {
83         if (idx < 3)
84         {
85             vaddr = m_v_addr[idx];
86             isa = m_v_addr_ISA[idx];
87         }
88     }
89 
90 private:
91     ocsd_pkt_vaddr m_v_addr[3];         //!< most recently broadcast address packet
92     uint8_t        m_v_addr_ISA[3];
93 };
94 
95 /*!
96  * @class EtmV4ITrcPacket
97  * @brief ETMv4 Instuction Trace Protocol Packet.
98  * @ingroup trc_pkts
99  *
100  *  This class represents a single ETMv4 data trace packet, along with intra packet state.
101  *
102  */
103 class EtmV4ITrcPacket :  public TrcPacketBase, public ocsd_etmv4_i_pkt, public trcPrintableElem
104 {
105 public:
106     EtmV4ITrcPacket();
107     ~EtmV4ITrcPacket();
108 
109     EtmV4ITrcPacket &operator =(const ocsd_etmv4_i_pkt* p_pkt);
110 
111     virtual const void *c_pkt() const { return (const ocsd_etmv4_i_pkt *)this; };
112 
113     // update interface - set packet values
114     void initStartState();   //!< Set to initial state - no intra packet state valid. Use on start of trace / discontinuities.
115     void initNextPacket();  //!< clear any single packet only flags / state.
116 
117     void setType(const ocsd_etmv4_i_pkt_type pkt_type) { type = pkt_type; };
118     void updateErrType(const ocsd_etmv4_i_pkt_type err_pkt_type);
119 
120     void clearTraceInfo();  //!< clear all the trace info data prior to setting for new trace info packet.
121     void setTraceInfo(const uint32_t infoVal);
122     void setTraceInfoKey(const uint32_t keyVal);
123     void setTraceInfoSpec(const uint32_t specVal);
124     void setTraceInfoCyct(const uint32_t cyctVal);
125 
126     void setTS(const uint64_t value, const uint8_t bits);
127     void setCycleCount(const uint32_t value);
128     void setCommitElements(const uint32_t commit_elem);
129     void setCancelElements(const uint32_t cancel_elem);
130     void setAtomPacket(const ocsd_pkt_atm_type type, const uint32_t En_bits, const uint8_t num);
131 
132     void setCondIF1(uint32_t const cond_key);
133     void setCondIF2(uint8_t const c_elem_idx);
134     void setCondIF3(uint8_t const num_c_elem, const bool finalElem);
135 
136     void setCondRF1(const uint32_t key[2], const uint8_t res[2], const uint8_t CI[2], const bool set2Keys);
137     void setCondRF2(const uint8_t key_incr, const uint8_t token);
138     void setCondRF3(const uint16_t tokens);
139     void setCondRF4(const uint8_t token);
140 
141     void setContextInfo(const bool update, const uint8_t EL = 0, const uint8_t NS = 0, const uint8_t SF = 0);
142     void setContextVMID(const uint32_t VMID);
143     void setContextCID(const uint32_t CID);
144 
145     void setExceptionInfo(const uint16_t excep_type, const uint8_t addr_interp, const uint8_t m_fault_pending, const uint8_t m_type);
146 
147     void set64BitAddress(const uint64_t addr, const uint8_t IS);
148     void set32BitAddress(const uint32_t addr, const uint8_t IS);
149     void updateShortAddress(const uint32_t addr, const uint8_t IS, const uint8_t update_bits);
150     void setAddressExactMatch(const uint8_t idx);
151 
152     void setDataSyncMarker(const uint8_t dsm_val);
153     void setEvent(const uint8_t event_val);
154 
155     void setQType(const bool has_count, const uint32_t count, const bool has_addr, const bool addr_match, const uint8_t type);
156 
157     // packet status interface - get packet info.
158     const ocsd_etmv4_i_pkt_type getType() const { return type; };
159     const ocsd_etmv4_i_pkt_type getErrType() const { return err_type; };
160 
161     //! return true if this packet has set the commit packet count.
162     const bool hasCommitElementsCount() const
163     {
164         return pkt_valid.bits.commit_elem_valid ? true : false;
165     };
166 
167     // trace info
168     const etmv4_trace_info_t &getTraceInfo() const { return trace_info; };
169     const uint32_t getCCThreshold() const;
170     const uint32_t getP0Key() const;
171     const uint32_t getCurrSpecDepth() const;
172 
173     // atom
174     const ocsd_pkt_atom &getAtom() const { return atom; };
175 
176     // context
177     const etmv4_context_t &getContext() const { return context; };
178 
179     // address
180     const uint8_t &getAddrMatch() const  { return addr_exact_match_idx; };
181     const ocsd_vaddr_t &getAddrVal() const { return v_addr.val; };
182     const uint8_t &getAddrIS() const { return v_addr_ISA; };
183     const bool getAddr64Bit() const { return v_addr.size == VA_64BIT; };
184 
185     // ts
186     const uint64_t getTS() const { return pkt_valid.bits.ts_valid ? ts.timestamp : 0; };
187 
188     // cc
189     const uint32_t getCC() const { return pkt_valid.bits.cc_valid ? cycle_count : 0; };
190 
191     // packet type
192     const bool isBadPacket() const;
193 
194     // printing
195     virtual void toString(std::string &str) const;
196     virtual void toStringFmt(const uint32_t fmtFlags, std::string &str) const;
197 
198 private:
199     const char *packetTypeName(const ocsd_etmv4_i_pkt_type type, const char **pDesc) const;
200     void contextStr(std::string &ctxtStr) const;
201     void atomSeq(std::string &valStr) const;
202     void addrMatchIdx(std::string &valStr) const;
203     void exceptionInfo(std::string &valStr) const;
204 
205     void push_vaddr();
206     void pop_vaddr_idx(const uint8_t idx);
207 
208     Etmv4PktAddrStack m_addr_stack;
209 };
210 
211 inline void  EtmV4ITrcPacket::updateErrType(const ocsd_etmv4_i_pkt_type err_pkt_type)
212 {
213     // set primary type to incoming error type, set packet err type to previous primary type.
214     err_type = type;
215     type = err_pkt_type;
216 }
217 
218 inline void EtmV4ITrcPacket::clearTraceInfo()
219 {
220     pkt_valid.bits.ts_valid = 0;
221     pkt_valid.bits.trace_info_valid = 0;
222     pkt_valid.bits.p0_key_valid = 0;
223     pkt_valid.bits.spec_depth_valid = 0;
224     pkt_valid.bits.cc_thresh_valid  = 0;
225 
226     pkt_valid.bits.ts_valid = 0;    // mark TS as invalid - must be re-updated after trace info.
227 }
228 
229 inline void EtmV4ITrcPacket::setTraceInfo(const uint32_t infoVal)
230 {
231     trace_info.val = infoVal;
232     pkt_valid.bits.trace_info_valid = 1;
233 }
234 
235 inline void EtmV4ITrcPacket::setTraceInfoKey(const uint32_t keyVal)
236 {
237     p0_key = keyVal;
238     pkt_valid.bits.p0_key_valid = 1;
239 }
240 
241 inline void EtmV4ITrcPacket::setTraceInfoSpec(const uint32_t specVal)
242 {
243     curr_spec_depth = specVal;
244     pkt_valid.bits.spec_depth_valid = 1;
245 }
246 
247 inline void EtmV4ITrcPacket::setTraceInfoCyct(const uint32_t cyctVal)
248 {
249     cc_threshold = cyctVal;
250     pkt_valid.bits.cc_thresh_valid  = 1;
251 }
252 
253 inline void EtmV4ITrcPacket::setTS(const uint64_t value, const uint8_t bits)
254 {
255     uint64_t mask = (uint64_t)-1LL;
256     if(bits < 64) mask = (1ULL << bits) - 1;
257     ts.timestamp = (ts.timestamp & ~mask) | (value & mask);
258     ts.bits_changed = bits;
259     pkt_valid.bits.ts_valid = 1;
260 }
261 
262 inline void EtmV4ITrcPacket::setCycleCount(const uint32_t value)
263 {
264     pkt_valid.bits.cc_valid = 1;
265     cycle_count = value;
266 }
267 
268 inline void EtmV4ITrcPacket::setCommitElements(const uint32_t commit_elem)
269 {
270     pkt_valid.bits.commit_elem_valid = 1;
271     commit_elements = commit_elem;
272 }
273 
274 inline const uint32_t EtmV4ITrcPacket::getCCThreshold() const
275 {
276     if(pkt_valid.bits.cc_thresh_valid)
277         return cc_threshold;
278     return 0;
279 }
280 
281 inline const uint32_t EtmV4ITrcPacket::getP0Key() const
282 {
283     if(pkt_valid.bits.p0_key_valid)
284         return p0_key;
285     return 0;
286 }
287 
288 inline const uint32_t EtmV4ITrcPacket::getCurrSpecDepth() const
289 {
290     if(pkt_valid.bits.spec_depth_valid)
291         return curr_spec_depth;
292     return 0;
293 }
294 
295 inline void EtmV4ITrcPacket::setCancelElements(const uint32_t cancel_elem)
296 {
297     cancel_elements = cancel_elem;
298 }
299 
300 inline void EtmV4ITrcPacket::setAtomPacket(const ocsd_pkt_atm_type type, const uint32_t En_bits, const uint8_t num)
301 {
302     if(type == ATOM_REPEAT)
303     {
304         uint32_t bit_patt = En_bits & 0x1;
305         if(bit_patt)
306         {
307             // none zero - all 1s
308             bit_patt = (bit_patt << num) - 1;
309         }
310         atom.En_bits = bit_patt;
311     }
312     else
313         atom.En_bits = En_bits;
314     atom.num = num;
315 }
316 
317 inline void EtmV4ITrcPacket::setCondIF1(const uint32_t cond_key)
318 {
319     cond_instr.cond_key_set = 1;
320     cond_instr.f3_final_elem = 0;
321     cond_instr.f2_cond_incr = 0;
322     cond_instr.num_c_elem = 1;
323     cond_instr.cond_c_key = cond_key;
324 }
325 
326 inline void EtmV4ITrcPacket::setCondIF2(const uint8_t c_elem_idx)
327 {
328     cond_instr.cond_key_set = 0;
329     cond_instr.f3_final_elem = 0;
330     switch(c_elem_idx & 0x3)
331     {
332     case 0:
333         cond_instr.f2_cond_incr = 1;
334         cond_instr.num_c_elem = 1;
335         break;
336 
337     case 1:
338         cond_instr.f2_cond_incr = 0;
339         cond_instr.num_c_elem = 1;
340         break;
341 
342     case 2:
343         cond_instr.f2_cond_incr = 1;
344         cond_instr.num_c_elem = 2;
345         break;
346     }
347 }
348 
349 inline void EtmV4ITrcPacket::setCondIF3(const uint8_t num_c_elem, const bool finalElem)
350 {
351     cond_instr.cond_key_set = 0;
352     cond_instr.f3_final_elem = finalElem ? 1: 0;
353     cond_instr.f2_cond_incr = 0;
354     cond_instr.num_c_elem = num_c_elem;
355 }
356 
357 inline void EtmV4ITrcPacket::setCondRF1(const uint32_t key[2], const uint8_t res[2], const uint8_t CI[2],const bool set2Keys)
358 {
359     cond_result.key_res_0_set = 1;
360     cond_result.cond_r_key_0 = key[0];
361     cond_result.res_0 = res[0];
362     cond_result.ci_0 = CI[0];
363 
364     if(set2Keys)
365     {
366         cond_result.key_res_1_set = 1;
367         cond_result.cond_r_key_1 = key[1];
368         cond_result.res_1 = res[1];
369         cond_result.ci_1 = CI[1];
370     }
371 }
372 
373 
374 inline void EtmV4ITrcPacket::setCondRF2(const uint8_t key_incr, const uint8_t token)
375 {
376     cond_result.key_res_0_set = 0;
377     cond_result.key_res_1_set = 0;
378     cond_result.f2_key_incr = key_incr;
379     cond_result.f2f4_token = token;
380 }
381 
382 inline void EtmV4ITrcPacket::setCondRF3(const uint16_t tokens)
383 {
384     cond_result.key_res_0_set = 0;
385     cond_result.key_res_1_set = 0;
386     cond_result.f3_tokens = tokens;
387 }
388 
389 inline void EtmV4ITrcPacket::setCondRF4(const uint8_t token)
390 {
391     cond_result.key_res_0_set = 0;
392     cond_result.key_res_1_set = 0;
393     cond_result.f2f4_token = token;
394 }
395 
396 inline void EtmV4ITrcPacket::setContextInfo(const bool update, const uint8_t EL, const uint8_t NS, const uint8_t SF)
397 {
398     pkt_valid.bits.context_valid = 1;
399     if(update)
400     {
401         context.updated = 1;
402         context.EL = EL;
403         context.NS = NS;
404         context.SF = SF;
405     }
406 }
407 
408 inline void EtmV4ITrcPacket::setContextVMID(const uint32_t VMID)
409 {
410     pkt_valid.bits.context_valid = 1;
411     context.updated = 1;
412     context.VMID = VMID;
413     context.updated_v = 1;
414 }
415 
416 inline void EtmV4ITrcPacket::setContextCID(const uint32_t CID)
417 {
418     pkt_valid.bits.context_valid = 1;
419     context.updated = 1;
420     context.ctxtID = CID;
421     context.updated_c = 1;
422 }
423 
424 inline void EtmV4ITrcPacket::setExceptionInfo(const uint16_t excep_type, const uint8_t addr_interp, const uint8_t m_fault_pending, const uint8_t m_type)
425 {
426     exception_info.exceptionType = excep_type;
427     exception_info.addr_interp = addr_interp;
428     exception_info.m_fault_pending = m_fault_pending;
429     exception_info.m_type = m_type;
430 }
431 
432 inline void EtmV4ITrcPacket::set64BitAddress(const uint64_t addr, const uint8_t IS)
433 {
434     v_addr.pkt_bits = 64;
435     v_addr.valid_bits = 64;
436     v_addr.size = VA_64BIT;
437     v_addr.val = addr;
438     v_addr_ISA = IS;
439     push_vaddr();
440 }
441 
442 inline void EtmV4ITrcPacket::set32BitAddress(const uint32_t addr, const uint8_t IS)
443 {
444     uint64_t mask = OCSD_BIT_MASK(32);
445     v_addr.pkt_bits = 32;
446 
447     if (pkt_valid.bits.context_valid && context.SF)
448         v_addr.size = VA_64BIT;
449     else
450     {
451         v_addr.val &= 0xFFFFFFFF;   // ensure vaddr is only 32 bits if not 64 bit
452         v_addr.size = VA_32BIT;
453     }
454 
455     if (v_addr.valid_bits < 32) // may be 64 bit address so only set 32 if less
456         v_addr.valid_bits = 32;
457 
458     v_addr.val = (v_addr.val & ~mask) | (addr & mask);
459     v_addr_ISA = IS;
460     push_vaddr();
461 }
462 
463 inline void EtmV4ITrcPacket::updateShortAddress(const uint32_t addr, const uint8_t IS, const uint8_t update_bits)
464 {
465     ocsd_vaddr_t update_mask = OCSD_BIT_MASK(update_bits);
466     v_addr.pkt_bits = update_bits;
467     if(v_addr.valid_bits < update_bits)
468         v_addr.valid_bits = update_bits;
469 
470     v_addr.val = (v_addr.val & ~update_mask) | (addr & update_mask);
471     v_addr_ISA = IS;
472     push_vaddr();
473 }
474 
475 inline void EtmV4ITrcPacket::setAddressExactMatch(const uint8_t idx)
476 {
477     addr_exact_match_idx = idx;
478     pop_vaddr_idx(idx);
479     push_vaddr();
480 }
481 
482 inline void EtmV4ITrcPacket::setDataSyncMarker(const uint8_t dsm_value)
483 {
484     dsm_val = dsm_value;
485 }
486 
487 inline void EtmV4ITrcPacket::setEvent(const uint8_t event_value)
488 {
489     event_val = event_value;
490 }
491 
492 inline void EtmV4ITrcPacket::setQType(const bool has_count, const uint32_t count, const bool has_addr, const bool addr_match, const uint8_t type)
493 {
494     Q_pkt.q_count = count;
495     Q_pkt.q_type = type;
496     Q_pkt.count_present = has_count ? 1 : 0;
497     Q_pkt.addr_present = has_addr ? 1: 0;
498     Q_pkt.addr_match = addr_match ? 1 :0;
499 }
500 
501 inline const bool EtmV4ITrcPacket::isBadPacket() const
502 {
503     return (type >= ETM4_PKT_I_BAD_SEQUENCE);
504 }
505 
506 inline void  EtmV4ITrcPacket::push_vaddr()
507 {
508     m_addr_stack.push(v_addr, v_addr_ISA);
509 }
510 
511 inline void EtmV4ITrcPacket::pop_vaddr_idx(const uint8_t idx)
512 {
513     m_addr_stack.get_idx(idx, v_addr, v_addr_ISA);
514 }
515 
516 /** @}*/
517 
518 #endif // ARM_TRC_PKT_ELEM_ETMV4I_H_INCLUDED
519 
520 /* End of File trc_pkt_elem_etmv4i.h */
521