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