diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 07:24:57 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 07:24:57 +0000 |
commit | 070852d8604cece0c31f28ff3eb8d21d9ba415fb (patch) | |
tree | 9097175a6a5b8b7e37af9a96269ac0b61a0189cd /decoder/include/opencsd/etmv4 | |
parent | Initial commit. (diff) | |
download | libopencsd-070852d8604cece0c31f28ff3eb8d21d9ba415fb.tar.xz libopencsd-070852d8604cece0c31f28ff3eb8d21d9ba415fb.zip |
Adding upstream version 1.3.3.upstream/1.3.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'decoder/include/opencsd/etmv4')
-rw-r--r-- | decoder/include/opencsd/etmv4/etmv4_decoder.h | 47 | ||||
-rw-r--r-- | decoder/include/opencsd/etmv4/trc_cmp_cfg_etmv4.h | 492 | ||||
-rw-r--r-- | decoder/include/opencsd/etmv4/trc_dcd_mngr_etmv4i.h | 31 | ||||
-rw-r--r-- | decoder/include/opencsd/etmv4/trc_etmv4_stack_elem.h | 477 | ||||
-rw-r--r-- | decoder/include/opencsd/etmv4/trc_pkt_decode_etmv4i.h | 250 | ||||
-rw-r--r-- | decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4i.h | 546 | ||||
-rw-r--r-- | decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4.h | 47 | ||||
-rw-r--r-- | decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4i.h | 215 | ||||
-rw-r--r-- | decoder/include/opencsd/etmv4/trc_pkt_types_etmv4.h | 392 |
9 files changed, 2497 insertions, 0 deletions
diff --git a/decoder/include/opencsd/etmv4/etmv4_decoder.h b/decoder/include/opencsd/etmv4/etmv4_decoder.h new file mode 100644 index 0000000..5d18363 --- /dev/null +++ b/decoder/include/opencsd/etmv4/etmv4_decoder.h @@ -0,0 +1,47 @@ +/* + * \file etmv4_decoder.h + * \brief OpenCSD : Top level header file for ETMv4 decoders + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ + + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ARM_ETMV4_DECODER_H_INCLUDED +#define ARM_ETMV4_DECODER_H_INCLUDED + +#include "trc_cmp_cfg_etmv4.h" +#include "trc_pkt_elem_etmv4i.h" +#include "trc_pkt_proc_etmv4.h" +#include "trc_pkt_types_etmv4.h" +#include "trc_pkt_decode_etmv4i.h" + +#endif // ARM_ETMV4_DECODER_H_INCLUDED + +/* End of File etmv4_decoder.h */ diff --git a/decoder/include/opencsd/etmv4/trc_cmp_cfg_etmv4.h b/decoder/include/opencsd/etmv4/trc_cmp_cfg_etmv4.h new file mode 100644 index 0000000..223dbda --- /dev/null +++ b/decoder/include/opencsd/etmv4/trc_cmp_cfg_etmv4.h @@ -0,0 +1,492 @@ +/* + * \file trc_cmp_cfg_etmv4.h + * \brief OpenCSD : + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ + + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ARM_TRC_CMP_CFG_ETMV4_H_INCLUDED +#define ARM_TRC_CMP_CFG_ETMV4_H_INCLUDED + +#include "trc_pkt_types_etmv4.h" +#include "common/trc_cs_config.h" + + +/** @addtogroup ocsd_protocol_cfg +@{*/ + +/** @name ETMv4 configuration +@{*/ + +/*! + * @class EtmV4Config + * @brief Interpreter class for etm v4 config structure. + * + * Provides quick value interpretation methods for the ETMv4 config register values. + * Primarily inlined for efficient code. + */ +class EtmV4Config : public CSConfig // public ocsd_etmv4_cfg +{ +public: + EtmV4Config(); /**< Default constructor */ + EtmV4Config(const ocsd_etmv4_cfg *cfg_regs); + ~EtmV4Config() {}; /**< Default destructor */ + +// operations to convert to and from C-API structure + + //! copy assignment operator for base structure into class. + EtmV4Config & operator=(const ocsd_etmv4_cfg *p_cfg); + + //! cast operator returning struct const reference + operator const ocsd_etmv4_cfg &() const { return m_cfg; }; + //! cast operator returning struct const pointer + operator const ocsd_etmv4_cfg *() const { return &m_cfg; }; + + const ocsd_core_profile_t &coreProfile() const { return m_cfg.core_prof; }; + const ocsd_arch_version_t &archVersion() const { return m_cfg.arch_ver; }; + + /* idr 0 */ + const bool LSasInstP0() const; + const bool hasDataTrace() const; + const bool hasBranchBroadcast() const; + const bool hasCondTrace() const; + const bool hasCycleCountI() const; + const bool hasRetStack() const; + const uint8_t numEvents() const; + const bool eteHasTSMarker() const; + + typedef enum _condType { + COND_PASS_FAIL, + COND_HAS_ASPR + } condType; + + const condType hasCondType() const; + + typedef enum _QSuppType { + Q_NONE, + Q_ICOUNT_ONLY, + Q_NO_ICOUNT_ONLY, + Q_FULL + } QSuppType; + + const QSuppType getQSuppType(); + const bool hasQElem(); + const bool hasQFilter(); + + const bool hasTrcExcpData() const; + const uint32_t TimeStampSize() const; + + const bool commitOpt1() const; + const bool commTransP0() const; + + /* idr 1 */ + const uint8_t MajVersion() const; + const uint8_t MinVersion() const; + const uint8_t FullVersion() const; + + /* idr 2 */ + const uint32_t iaSizeMax() const; + const uint32_t cidSize() const; + const uint32_t vmidSize(); + const uint32_t daSize() const; + const uint32_t dvSize() const; + const uint32_t ccSize() const; + const bool vmidOpt() const; + const bool wfiwfeBranch() const; + + /* id regs 8-13*/ + const uint32_t MaxSpecDepth() const; + const uint32_t P0_Key_Max() const; + const uint32_t P1_Key_Max() const; + const uint32_t P1_Spcl_Key_Max() const; + const uint32_t CondKeyMax() const; + const uint32_t CondSpecKeyMax() const; + const uint32_t CondKeyMaxIncr() const; + + /* trace idr */ + virtual const uint8_t getTraceID() const; //!< CoreSight Trace ID for this device. + + /* config R */ + const bool enabledDVTrace() const; + const bool enabledDATrace() const; + const bool enabledDataTrace() const; + + typedef enum { + LSP0_NONE, + LSP0_L, + LSP0_S, + LSP0_LS + } LSP0_t; + + const bool enabledLSP0Trace() const; + const LSP0_t LSP0Type() const; + + const bool enabledBrBroad() const; + const bool enabledCCI() const; + const bool enabledCID() const; + const bool enabledVMID() const; + const bool enabledVMIDOpt() const; + + typedef enum { + COND_TR_DIS, + COND_TR_LD, + COND_TR_ST, + COND_TR_LDST, + COND_TR_ALL + } CondITrace_t; + + const CondITrace_t enabledCondITrace(); + + const bool enabledTS() const; + const bool enabledRetStack() const; + + const bool enabledQE() const; + +private: + void PrivateInit(); + void CalcQSupp(); + void CalcVMIDSize(); + + bool m_QSuppCalc; + bool m_QSuppFilter; + QSuppType m_QSuppType; + + bool m_VMIDSzCalc; + uint32_t m_VMIDSize; + + bool m_condTraceCalc; + CondITrace_t m_CondTrace; + +protected: + ocsd_etmv4_cfg m_cfg; + uint8_t m_MajVer; + uint8_t m_MinVer; + +}; + +/* idr 0 */ +inline const bool EtmV4Config::LSasInstP0() const +{ + return (bool)((m_cfg.reg_idr0 & 0x6) == 0x6); +} + +inline const bool EtmV4Config::hasDataTrace() const +{ + return (bool)((m_cfg.reg_idr0 & 0x18) == 0x18); +} + +inline const bool EtmV4Config::hasBranchBroadcast() const +{ + return (bool)((m_cfg.reg_idr0 & 0x20) == 0x20); +} + +inline const bool EtmV4Config::hasCondTrace() const +{ + return (bool)((m_cfg.reg_idr0 & 0x40) == 0x40); +} + +inline const bool EtmV4Config::hasCycleCountI() const +{ + return (bool)((m_cfg.reg_idr0 & 0x80) == 0x80); +} + +inline const bool EtmV4Config::hasRetStack() const +{ + return (bool)((m_cfg.reg_idr0 & 0x200) == 0x200); +} + +inline const uint8_t EtmV4Config::numEvents() const +{ + return ((m_cfg.reg_idr0 >> 10) & 0x3) + 1; +} + +inline const EtmV4Config::condType EtmV4Config::hasCondType() const +{ + return ((m_cfg.reg_idr0 & 0x3000) == 0x1000) ? EtmV4Config::COND_HAS_ASPR : EtmV4Config::COND_PASS_FAIL; +} + +inline const EtmV4Config::QSuppType EtmV4Config::getQSuppType() +{ + if(!m_QSuppCalc) CalcQSupp(); + return m_QSuppType; +} + +inline const bool EtmV4Config::hasQElem() +{ + if(!m_QSuppCalc) CalcQSupp(); + return (bool)(m_QSuppType != Q_NONE); +} + +inline const bool EtmV4Config::hasQFilter() +{ + if(!m_QSuppCalc) CalcQSupp(); + return m_QSuppFilter; +} + +inline const bool EtmV4Config::hasTrcExcpData() const +{ + return (bool)((m_cfg.reg_idr0 & 0x20000) == 0x20000); +} + +inline const bool EtmV4Config::eteHasTSMarker() const +{ + return (FullVersion() >= 0x51) && ((m_cfg.reg_idr0 & 0x800000) == 0x800000); +} + +inline const uint32_t EtmV4Config::TimeStampSize() const +{ + uint32_t tsSizeF = (m_cfg.reg_idr0 >> 24) & 0x1F; + if(tsSizeF == 0x6) + return 48; + if(tsSizeF == 0x8) + return 64; + return 0; +} + +inline const bool EtmV4Config::commitOpt1() const +{ + return (bool)((m_cfg.reg_idr0 & 0x20000000) == 0x20000000) && hasCycleCountI(); +} + +inline const bool EtmV4Config::commTransP0() const +{ + return (bool)((m_cfg.reg_idr0 & 0x40000000) == 0x0); +} + + /* idr 1 */ +inline const uint8_t EtmV4Config::MajVersion() const +{ + return m_MajVer; +} + +inline const uint8_t EtmV4Config::MinVersion() const +{ + return m_MinVer; +} + +inline const uint8_t EtmV4Config::FullVersion() const +{ + return (m_MajVer << 4) | m_MinVer; +} + +/* idr 2 */ +inline const uint32_t EtmV4Config::iaSizeMax() const +{ + return ((m_cfg.reg_idr2 & 0x1F) == 0x8) ? 64 : 32; +} + +inline const uint32_t EtmV4Config::cidSize() const +{ + return (((m_cfg.reg_idr2 >> 5) & 0x1F) == 0x4) ? 32 : 0; +} + +inline const uint32_t EtmV4Config::vmidSize() +{ + if(!m_VMIDSzCalc) + { + CalcVMIDSize(); + } + return m_VMIDSize; +} + +inline const uint32_t EtmV4Config::daSize() const +{ + uint32_t daSizeF = ((m_cfg.reg_idr2 >> 15) & 0x1F); + if(daSizeF) + return (((m_cfg.reg_idr2 >> 15) & 0x1F) == 0x8) ? 64 : 32; + return 0; +} + +inline const uint32_t EtmV4Config::dvSize() const +{ + uint32_t dvSizeF = ((m_cfg.reg_idr2 >> 20) & 0x1F); + if(dvSizeF) + return (((m_cfg.reg_idr2 >> 20) & 0x1F) == 0x8) ? 64 : 32; + return 0; +} + +inline const uint32_t EtmV4Config::ccSize() const +{ + return ((m_cfg.reg_idr2 >> 25) & 0xF) + 12; +} + +inline const bool EtmV4Config::vmidOpt() const +{ + return (bool)((m_cfg.reg_idr2 & 0x20000000) == 0x20000000) && (MinVersion() > 0); +} + +inline const bool EtmV4Config::wfiwfeBranch() const +{ + return (bool)((m_cfg.reg_idr2 & 0x80000000) && (FullVersion() >= 0x43)); +} + + +/* id regs 8-13*/ + +inline const uint32_t EtmV4Config::MaxSpecDepth() const +{ + return m_cfg.reg_idr8; +} + +inline const uint32_t EtmV4Config::P0_Key_Max() const +{ + return (m_cfg.reg_idr9 == 0) ? 1 : m_cfg.reg_idr9; +} + +inline const uint32_t EtmV4Config::P1_Key_Max() const +{ + return m_cfg.reg_idr10; +} + +inline const uint32_t EtmV4Config::P1_Spcl_Key_Max() const +{ + return m_cfg.reg_idr11; +} + +inline const uint32_t EtmV4Config::CondKeyMax() const +{ + return m_cfg.reg_idr12; +} + +inline const uint32_t EtmV4Config::CondSpecKeyMax() const +{ + return m_cfg.reg_idr13; +} + +inline const uint32_t EtmV4Config::CondKeyMaxIncr() const +{ + return m_cfg.reg_idr12 - m_cfg.reg_idr13; +} + +inline const uint8_t EtmV4Config::getTraceID() const +{ + return (uint8_t)(m_cfg.reg_traceidr & 0x7F); +} + + /* config R */ +inline const bool EtmV4Config::enabledDVTrace() const +{ + return hasDataTrace() && enabledLSP0Trace() && ((m_cfg.reg_configr & (0x1 << 17)) != 0); +} + +inline const bool EtmV4Config::enabledDATrace() const +{ + return hasDataTrace() && enabledLSP0Trace() && ((m_cfg.reg_configr & (0x1 << 16)) != 0); +} + +inline const bool EtmV4Config::enabledDataTrace() const +{ + return enabledDATrace() || enabledDVTrace(); +} + +inline const bool EtmV4Config::enabledLSP0Trace() const +{ + return ((m_cfg.reg_configr & 0x6) != 0); +} + +inline const EtmV4Config::LSP0_t EtmV4Config::LSP0Type() const +{ + return (LSP0_t)((m_cfg.reg_configr & 0x6) >> 1); +} + +inline const bool EtmV4Config::enabledBrBroad() const +{ + return ((m_cfg.reg_configr & (0x1 << 3)) != 0); +} + +inline const bool EtmV4Config::enabledCCI() const +{ + return ((m_cfg.reg_configr & (0x1 << 4)) != 0); +} + +inline const bool EtmV4Config::enabledCID() const +{ + return ((m_cfg.reg_configr & (0x1 << 6)) != 0); +} + +inline const bool EtmV4Config::enabledVMID() const +{ + return ((m_cfg.reg_configr & (0x1 << 7)) != 0); +} + +inline const bool EtmV4Config::enabledVMIDOpt() const +{ + bool vmidOptVal = ((m_cfg.reg_configr & (0x1 << 15)) != 0); + /* TRIDR2.VMIDOPT[30:29] determine value used */ + if (!vmidOpt()) { /* [29] = 1'b0 */ + vmidOptVal = false; /* res0 */ + if (FullVersion() >= 0x45) { + /* umless version > 4.5 in which case [30] determines res val */ + vmidOptVal = ((m_cfg.reg_idr2 & (0x1 << 30)) != 0); + } + } + return vmidOptVal; +} + +inline const EtmV4Config::CondITrace_t EtmV4Config::enabledCondITrace() +{ + if(!m_condTraceCalc) + { + switch((m_cfg.reg_configr >> 8) & 0x7) + { + default: + case 0: m_CondTrace = COND_TR_DIS; break; + case 1: m_CondTrace = COND_TR_LD; break; + case 2: m_CondTrace = COND_TR_ST; break; + case 3: m_CondTrace = COND_TR_LDST; break; + case 7: m_CondTrace = COND_TR_ALL; break; + } + m_condTraceCalc = true; + } + return m_CondTrace; +} + +inline const bool EtmV4Config::enabledTS() const +{ + return ((m_cfg.reg_configr & (0x1 << 11)) != 0); +} + +inline const bool EtmV4Config::enabledRetStack() const +{ + return ((m_cfg.reg_configr & (0x1 << 12)) != 0); +} + +inline const bool EtmV4Config::enabledQE() const +{ + return ((m_cfg.reg_configr & (0x3 << 13)) != 0); +} + +/** @}*/ +/** @}*/ + +#endif // ARM_TRC_CMP_CFG_ETMV4_H_INCLUDED + +/* End of File trc_cmp_cfg_etmv4.h */ diff --git a/decoder/include/opencsd/etmv4/trc_dcd_mngr_etmv4i.h b/decoder/include/opencsd/etmv4/trc_dcd_mngr_etmv4i.h new file mode 100644 index 0000000..a5b2540 --- /dev/null +++ b/decoder/include/opencsd/etmv4/trc_dcd_mngr_etmv4i.h @@ -0,0 +1,31 @@ +/* + * \file trc_dcd_mngr_etmv4i.h + * \brief Reference CoreSight Trace Decoder : + * + * \copyright Copyright (c) 2016, ARM Limited. All Rights Reserved. + */ + +#ifndef ARM_TRC_DCD_MNGR_ETMV4I_H_INCLUDED +#define ARM_TRC_DCD_MNGR_ETMV4I_H_INCLUDED + +#include "common/ocsd_dcd_mngr.h" +#include "trc_pkt_decode_etmv4i.h" +#include "trc_pkt_proc_etmv4.h" +#include "trc_cmp_cfg_etmv4.h" +#include "trc_pkt_types_etmv4.h" + +class DecoderMngrEtmV4I : public DecodeMngrFullDcd< EtmV4ITrcPacket, + ocsd_etmv4_i_pkt_type, + EtmV4Config, + ocsd_etmv4_cfg, + TrcPktProcEtmV4I, + TrcPktDecodeEtmV4I> +{ +public: + DecoderMngrEtmV4I(const std::string &name) : DecodeMngrFullDcd(name,OCSD_PROTOCOL_ETMV4I) {}; + virtual ~DecoderMngrEtmV4I() {}; +}; + +#endif // ARM_TRC_DCD_MNGR_ETMV4I_H_INCLUDED + +/* End of File trc_dcd_mngr_etmv4i.h */ diff --git a/decoder/include/opencsd/etmv4/trc_etmv4_stack_elem.h b/decoder/include/opencsd/etmv4/trc_etmv4_stack_elem.h new file mode 100644 index 0000000..c5c609c --- /dev/null +++ b/decoder/include/opencsd/etmv4/trc_etmv4_stack_elem.h @@ -0,0 +1,477 @@ +/* + * \file trc_etmv4_stack_elem.h + * \brief OpenCSD : + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef ARM_TRC_ETMV4_STACK_ELEM_H_INCLUDED +#define ARM_TRC_ETMV4_STACK_ELEM_H_INCLUDED + +#include "opencsd/etmv4/trc_pkt_types_etmv4.h" +#include "opencsd/trc_gen_elem_types.h" + +#include <deque> +#include <vector> + +/* ETMv4 I trace stack elements + Speculation requires that we stack certain elements till they are committed or + cancelled. (P0 elements + other associated parts.) +*/ + +typedef enum _p0_elem_t +{ + P0_UNKNOWN, + P0_ATOM, + P0_ADDR, + P0_CTXT, + P0_TRC_ON, + P0_EXCEP, + P0_EXCEP_RET, + P0_EVENT, + P0_TS, + P0_CC, + P0_TS_CC, + P0_MARKER, + P0_Q, + P0_OVERFLOW, + P0_FUNC_RET, + P0_SRC_ADDR, + P0_TRANS_TRACE_INIT, + P0_TRANS_START, + P0_TRANS_COMMIT, + P0_TRANS_FAIL +} p0_elem_t; + + +/************************************************************/ +/***Trace stack element base class - + record originating packet type and index in buffer*/ + +class TrcStackElem { +public: + TrcStackElem(const p0_elem_t p0_type, const bool isP0, const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index); + virtual ~TrcStackElem() {}; + + const p0_elem_t getP0Type() const { return m_P0_type; }; + const ocsd_etmv4_i_pkt_type getRootPkt() const { return m_root_pkt; }; + const ocsd_trc_index_t getRootIndex() const { return m_root_idx; }; + const bool isP0() const { return m_is_P0; }; + +private: + ocsd_etmv4_i_pkt_type m_root_pkt; + ocsd_trc_index_t m_root_idx; + p0_elem_t m_P0_type; + +protected: + bool m_is_P0; // true if genuine P0 - commit / cancellable, false otherwise + +}; + +inline TrcStackElem::TrcStackElem(p0_elem_t p0_type, const bool isP0, ocsd_etmv4_i_pkt_type root_pkt, ocsd_trc_index_t root_index) : + m_root_pkt(root_pkt), + m_root_idx(root_index), + m_P0_type(p0_type), + m_is_P0(isP0) +{ +} + +/************************************************************/ +/** Address element */ + +class TrcStackElemAddr : public TrcStackElem +{ +protected: + TrcStackElemAddr(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index); + TrcStackElemAddr(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const bool src_addr); + virtual ~TrcStackElemAddr() {}; + + friend class EtmV4P0Stack; + +public: + void setAddr(const etmv4_addr_val_t &addr_val) { m_addr_val = addr_val; }; + const etmv4_addr_val_t &getAddr() const { return m_addr_val; }; + +private: + etmv4_addr_val_t m_addr_val; +}; + +inline TrcStackElemAddr::TrcStackElemAddr(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) : + TrcStackElem(P0_ADDR, false, root_pkt,root_index) +{ + m_addr_val.val = 0; + m_addr_val.isa = 0; +} + +inline TrcStackElemAddr::TrcStackElemAddr(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const bool src_addr) : + TrcStackElem(src_addr ? P0_SRC_ADDR : P0_ADDR, false, root_pkt, root_index) +{ + m_addr_val.val = 0; + m_addr_val.isa = 0; +} + + +/************************************************************/ +/** Q element */ +class TrcStackQElem : public TrcStackElem +{ +protected: + TrcStackQElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index); + virtual ~TrcStackQElem() {}; + + friend class EtmV4P0Stack; + +public: + void setInstrCount(const int instr_count) { m_instr_count = instr_count; }; + const int getInstrCount() const { return m_instr_count; } + + void setAddr(const etmv4_addr_val_t &addr_val) + { + m_addr_val = addr_val; + m_has_addr = true; + }; + const etmv4_addr_val_t &getAddr() const { return m_addr_val; }; + const bool hasAddr() const { return m_has_addr; }; + +private: + bool m_has_addr; + etmv4_addr_val_t m_addr_val; + int m_instr_count; + +}; + +inline TrcStackQElem::TrcStackQElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) : + TrcStackElem(P0_Q , true, root_pkt, root_index) +{ + m_addr_val.val = 0; + m_addr_val.isa = 0; + m_has_addr = false; + m_instr_count = 0; +} + +/************************************************************/ +/** Context element */ + +class TrcStackElemCtxt : public TrcStackElem +{ +protected: + TrcStackElemCtxt(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index); + virtual ~TrcStackElemCtxt() {}; + + friend class EtmV4P0Stack; + +public: + void setContext(const etmv4_context_t &ctxt) { m_context = ctxt; }; + const etmv4_context_t &getContext() const { return m_context; }; + void setIS(const uint8_t IS) { m_IS = IS; }; + const uint8_t getIS() const { return m_IS; }; + +private: + etmv4_context_t m_context; + uint8_t m_IS; //!< IS value at time of generation of packet. +}; + +inline TrcStackElemCtxt::TrcStackElemCtxt(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) : + TrcStackElem(P0_CTXT, false, root_pkt,root_index) +{ +} + +/************************************************************/ +/** Exception element */ + +class TrcStackElemExcept : public TrcStackElem +{ +protected: + TrcStackElemExcept(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index); + virtual ~TrcStackElemExcept() {}; + + friend class EtmV4P0Stack; + +public: + void setPrevSame(bool bSame) { m_prev_addr_same = bSame; }; + const bool getPrevSame() const { return m_prev_addr_same; }; + + void setExcepNum(const uint16_t num) { m_excep_num = num; }; + const uint16_t getExcepNum() const { return m_excep_num; }; + +private: + bool m_prev_addr_same; + uint16_t m_excep_num; +}; + +inline TrcStackElemExcept::TrcStackElemExcept(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) : + TrcStackElem(P0_EXCEP, true, root_pkt,root_index), + m_prev_addr_same(false) +{ +} + +/************************************************************/ +/** Atom element */ + +class TrcStackElemAtom : public TrcStackElem +{ +protected: + TrcStackElemAtom(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index); + virtual ~TrcStackElemAtom() {}; + + friend class EtmV4P0Stack; + +public: + void setAtom(const ocsd_pkt_atom &atom) { m_atom = atom; }; + + const ocsd_atm_val commitOldest(); + int cancelNewest(const int nCancel); + void mispredictNewest(); + const bool isEmpty() const { return (m_atom.num == 0); }; + +private: + ocsd_pkt_atom m_atom; +}; + +inline TrcStackElemAtom::TrcStackElemAtom(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) : + TrcStackElem(P0_ATOM, true, root_pkt,root_index) +{ + m_atom.num = 0; +} + +// commit oldest - get value and remove it from pattern +inline const ocsd_atm_val TrcStackElemAtom::commitOldest() +{ + ocsd_atm_val val = (m_atom.En_bits & 0x1) ? ATOM_E : ATOM_N; + m_atom.num--; + m_atom.En_bits >>= 1; + return val; +} + +// cancel newest - just reduce the atom count. +inline int TrcStackElemAtom::cancelNewest(const int nCancel) +{ + int nRemove = (nCancel <= m_atom.num) ? nCancel : m_atom.num; + m_atom.num -= nRemove; + return nRemove; +} + +// mispredict newest - flip the bit of the newest atom +inline void TrcStackElemAtom::mispredictNewest() +{ + uint32_t mask = 0x1 << (m_atom.num - 1); + if (m_atom.En_bits & mask) + m_atom.En_bits &= ~mask; + else + m_atom.En_bits |= mask; +} + +/************************************************************/ +/** Generic param element */ + +class TrcStackElemParam : public TrcStackElem +{ +protected: + TrcStackElemParam(const p0_elem_t p0_type, const bool isP0, const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index); + virtual ~TrcStackElemParam() {}; + + friend class EtmV4P0Stack; + +public: + void setParam(const uint32_t param, const int nParamNum) { m_param[(nParamNum & 0x3)] = param; }; + const uint32_t &getParam(const int nParamNum) const { return m_param[(nParamNum & 0x3)]; }; + +private: + uint32_t m_param[4]; +}; + +inline TrcStackElemParam::TrcStackElemParam(const p0_elem_t p0_type, const bool isP0, const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) : + TrcStackElem(p0_type, isP0, root_pkt,root_index) +{ +} + +/************************************************************/ +/** Marker element */ + +class TrcStackElemMarker : public TrcStackElem +{ +protected: + TrcStackElemMarker(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index); + virtual ~TrcStackElemMarker() {}; + + friend class EtmV4P0Stack; + +public: + void setMarker(const trace_marker_payload_t &marker) { m_marker = marker; }; + const trace_marker_payload_t &getMarker() const { return m_marker; }; + +private: + trace_marker_payload_t m_marker; +}; + +inline TrcStackElemMarker::TrcStackElemMarker(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) : + TrcStackElem(P0_MARKER, false, root_pkt, root_index) +{ +} + + +/************************************************************/ +/* P0 element stack that allows push of elements, and deletion of elements when done. +*/ +class EtmV4P0Stack +{ +public: + EtmV4P0Stack() {}; + ~EtmV4P0Stack(); + + void push_front(TrcStackElem *pElem); + void push_back(TrcStackElem *pElem); // insert element when processing + void pop_back(bool pend_delete = true); + void pop_front(bool pend_delete = true); + TrcStackElem *back(); + TrcStackElem *front(); + size_t size(); + + // iterate through stack from front + void from_front_init(); + TrcStackElem *from_front_next(); + void erase_curr_from_front(); // erase the element last returned + + void delete_all(); + void delete_back(); + void delete_front(); + void delete_popped(); + + // creation functions - create and push if successful. + TrcStackElemParam *createParamElem(const p0_elem_t p0_type, const bool isP0, const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const std::vector<uint32_t> ¶ms); + TrcStackElem *createParamElemNoParam(const p0_elem_t p0_type, const bool isP0, const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, bool back = false); + TrcStackElemAtom *createAtomElem (const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const ocsd_pkt_atom &atom); + TrcStackElemExcept *createExceptElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const bool bSame, const uint16_t excepNum); + TrcStackElemCtxt *createContextElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const etmv4_context_t &context, const uint8_t IS, const bool back = false); + TrcStackElemAddr *createAddrElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const etmv4_addr_val_t &addr_val); + TrcStackQElem *createQElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const int count); + TrcStackElemMarker *createMarkerElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const trace_marker_payload_t &marker); + TrcStackElemAddr *createSrcAddrElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const etmv4_addr_val_t &addr_val); + +private: + std::deque<TrcStackElem *> m_P0_stack; //!< P0 decode element stack + std::vector<TrcStackElem *> m_popped_elem; //!< save list of popped but not deleted elements. + std::deque<TrcStackElem *>::iterator m_iter; //!< iterate across the list w/o removing stuff +}; + +inline EtmV4P0Stack::~EtmV4P0Stack() +{ + delete_all(); + delete_popped(); +} + +// put an element on the front of the stack +inline void EtmV4P0Stack::push_front(TrcStackElem *pElem) +{ + m_P0_stack.push_front(pElem); +} + +// put an element on the back of the stack +inline void EtmV4P0Stack::push_back(TrcStackElem *pElem) +{ + m_P0_stack.push_back(pElem); +} + +// pop last element pointer off the stack and stash it for later deletion +inline void EtmV4P0Stack::pop_back(bool pend_delete /* = true */) +{ + if (pend_delete) + m_popped_elem.push_back(m_P0_stack.back()); + m_P0_stack.pop_back(); +} + +inline void EtmV4P0Stack::pop_front(bool pend_delete /* = true */) +{ + if (pend_delete) + m_popped_elem.push_back(m_P0_stack.front()); + m_P0_stack.pop_front(); +} + +// pop last element pointer off the stack and delete immediately +inline void EtmV4P0Stack::delete_back() +{ + if (m_P0_stack.size() > 0) + { + TrcStackElem* pElem = m_P0_stack.back(); + delete pElem; + m_P0_stack.pop_back(); + } +} + +// pop first element pointer off the stack and delete immediately +inline void EtmV4P0Stack::delete_front() +{ + if (m_P0_stack.size() > 0) + { + TrcStackElem* pElem = m_P0_stack.front(); + delete pElem; + m_P0_stack.pop_front(); + } +} + + + +// get a pointer to the last element on the stack +inline TrcStackElem *EtmV4P0Stack::back() +{ + return m_P0_stack.back(); +} + +inline TrcStackElem *EtmV4P0Stack::front() +{ + return m_P0_stack.front(); +} + +// remove and delete all the elements left on the stack +inline void EtmV4P0Stack::delete_all() +{ + while (m_P0_stack.size() > 0) + delete_back(); + m_P0_stack.clear(); +} + +// delete list of popped elements. +inline void EtmV4P0Stack::delete_popped() +{ + while (m_popped_elem.size() > 0) + { + delete m_popped_elem.back(); + m_popped_elem.pop_back(); + } + m_popped_elem.clear(); +} + +// get current number of elements on the stack +inline size_t EtmV4P0Stack::size() +{ + return m_P0_stack.size(); +} + +#endif // ARM_TRC_ETMV4_STACK_ELEM_H_INCLUDED + +/* End of File trc_etmv4_stack_elem.h */ diff --git a/decoder/include/opencsd/etmv4/trc_pkt_decode_etmv4i.h b/decoder/include/opencsd/etmv4/trc_pkt_decode_etmv4i.h new file mode 100644 index 0000000..65230ff --- /dev/null +++ b/decoder/include/opencsd/etmv4/trc_pkt_decode_etmv4i.h @@ -0,0 +1,250 @@ +/* + * \file trc_pkt_decode_etmv4i.h + * \brief OpenCSD : ETMv4 instruction decoder + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ARM_TRC_PKT_DECODE_ETMV4I_H_INCLUDED +#define ARM_TRC_PKT_DECODE_ETMV4I_H_INCLUDED + +#include "common/trc_pkt_decode_base.h" +#include "opencsd/etmv4/trc_pkt_elem_etmv4i.h" +#include "opencsd/etmv4/trc_cmp_cfg_etmv4.h" +#include "common/trc_gen_elem.h" +#include "common/trc_ret_stack.h" +#include "common/ocsd_gen_elem_stack.h" +#include "opencsd/etmv4/trc_etmv4_stack_elem.h" + +class TrcStackElem; +class TrcStackElemParam; +class TrcStackElemCtxt; + +class TrcPktDecodeEtmV4I : public TrcPktDecodeBase<EtmV4ITrcPacket, EtmV4Config> +{ +public: + TrcPktDecodeEtmV4I(); + TrcPktDecodeEtmV4I(int instIDNum); + virtual ~TrcPktDecodeEtmV4I(); + +protected: + /* implementation packet decoding interface */ + virtual ocsd_datapath_resp_t processPacket(); + virtual ocsd_datapath_resp_t onEOT(); + virtual ocsd_datapath_resp_t onReset(); + virtual ocsd_datapath_resp_t onFlush(); + virtual ocsd_err_t onProtocolConfig(); + virtual const uint8_t getCoreSightTraceID() { return m_CSID; }; + + /* local decode methods */ + void initDecoder(); // initial state on creation (zeros all config) + void resetDecoder(); // reset state to start of decode. (moves state, retains config) + virtual void onFirstInitOK(); // override to set init related info. + + ocsd_err_t decodePacket(); // decode packet into trace elements. return true to indicate decode complete - can change FSM to commit state - return is false. + ocsd_datapath_resp_t resolveElements(); // commit/cancel trace elements generated from latest / prior packets & send to output - may get wait response, or flag completion. + ocsd_err_t commitElements(); // commit elements - process element stack to generate output packets. + ocsd_err_t commitElemOnEOT(); + ocsd_err_t cancelElements(); // cancel elements. These not output + ocsd_err_t mispredictAtom(); // mispredict an atom + ocsd_err_t discardElements(); // discard elements and flush + + void doTraceInfoPacket(); + void updateContext(TrcStackElemCtxt *pCtxtElem, OcsdTraceElement &elem); + + // process atom will create instruction trace, or no memory access trace output elements. + ocsd_err_t processAtom(const ocsd_atm_val atom); + + // process an exception element - output instruction trace + exception generic type. + ocsd_err_t processException(); + + // process Q element + ocsd_err_t processQElement(); + + // process a source address element + ocsd_err_t processSourceAddress(); + + // process an element that cannot be cancelled / discarded + ocsd_err_t processTS_CC_EventElem(TrcStackElem *pElem); + + // process marker elements + ocsd_err_t processMarkerElem(TrcStackElem *pElem); + + // process a transaction element + ocsd_err_t processTransElem(TrcStackElem *pElem); + + // process a bad packet + ocsd_err_t handleBadPacket(const char *reason, ocsd_trc_index_t index = OCSD_BAD_TRC_INDEX); + + // sequencing error on packet processing - optionally continue + ocsd_err_t handlePacketSeqErr(ocsd_err_t err, ocsd_trc_index_t index, const char *reason); + + // common packet error routine + ocsd_err_t handlePacketErr(ocsd_err_t err, ocsd_err_severity_t sev, ocsd_trc_index_t index, const char *reason); + + ocsd_err_t addElemCC(TrcStackElemParam *pParamElem); + ocsd_err_t addElemTS(TrcStackElemParam *pParamElem, bool withCC); + ocsd_err_t addElemEvent(TrcStackElemParam *pParamElem); + +private: + void SetInstrInfoInAddrISA(const ocsd_vaddr_t addr_val, const uint8_t isa); + const ocsd_isa calcISA(const bool SF, const uint8_t IS) const + { + if (SF) + return ocsd_isa_aarch64; + return (IS == 0) ? ocsd_isa_arm : ocsd_isa_thumb2; + } + typedef enum { + WP_NOT_FOUND, + WP_FOUND, + WP_NACC + } WP_res_t; + + typedef struct { + ocsd_vaddr_t st_addr; + ocsd_vaddr_t en_addr; + uint32_t num_instr; + } instr_range_t; + + //!< follow instructions from the current address to a WP. true if good, false if memory cannot be accessed. + ocsd_err_t traceInstrToWP(instr_range_t &instr_range, WP_res_t &WPRes, const bool traceToAddrNext = false, const ocsd_vaddr_t nextAddrMatch = 0); + + inline const bool WPFound(WP_res_t res) const { return (res == WP_FOUND); }; + inline const bool WPNacc(WP_res_t res) const { return (res == WP_NACC); }; + + ocsd_err_t returnStackPop(); // pop return stack and update instruction address. + + void setElemTraceRange(OcsdTraceElement &elemIn, const instr_range_t &addr_range, const bool executed, ocsd_trc_index_t index); + void setElemTraceRangeInstr(OcsdTraceElement &elemIn, const instr_range_t &addr_range, + const bool executed, ocsd_trc_index_t index, ocsd_instr_info &instr); + + // true if we are ETE configured. + inline bool isETEConfig() { + return (m_config->MajVersion() >= ETE_ARCH_VERSION); + } + + ocsd_mem_space_acc_t getCurrMemSpace(); + +//** intra packet state (see ETMv4 spec 6.2.1); + + // timestamping + uint64_t m_timestamp; // last broadcast global Timestamp. + bool m_ete_first_ts_marker; + + // state and context + uint32_t m_context_id; // most recent context ID + uint32_t m_vmid_id; // most recent VMID + bool m_is_secure; // true if Secure + bool m_is_64bit; // true if 64 bit + uint8_t m_last_IS; // last instruction set value from address packet. + + // cycle counts + int m_cc_threshold; + + // speculative trace + int m_curr_spec_depth; + int m_max_spec_depth; // nax depth - from ID reg, beyond which auto-commit occurs + int m_unseen_spec_elem; // speculative elements at decode start + +/** Remove elements that are associated with data trace */ +#ifdef DATA_TRACE_SUPPORTED + // data trace associative elements (unsupported at present in the decoder). + int m_p0_key; + int m_p0_key_max; + + // conditional non-branch trace - when data trace active (unsupported at present in the decoder) + int m_cond_c_key; + int m_cond_r_key; + int m_cond_key_max_incr; +#endif + + uint8_t m_CSID; //!< Coresight trace ID for this decoder. + + bool m_IASize64; //!< True if 64 bit instruction addresses supported. + +//** Other processor state; + + // trace decode FSM + typedef enum { + NO_SYNC, //!< pre start trace - init state or after reset or overflow, loss of sync. + WAIT_SYNC, //!< waiting for sync packet. + WAIT_TINFO, //!< waiting for trace info packet. + DECODE_PKTS, //!< processing packets - creating decode elements on stack + RESOLVE_ELEM, //!< analyze / resolve decode elements - create generic trace elements and pass on. + } processor_state_t; + + processor_state_t m_curr_state; + unsync_info_t m_unsync_eot_info; //!< addition info when / why unsync / eot + +//** P0 element stack + EtmV4P0Stack m_P0_stack; //!< P0 decode element stack + + // element resolution + struct { + int P0_commit; //!< number of elements to commit + int P0_cancel; //!< elements to cancel + bool mispredict; //!< mispredict latest atom + bool discard; //!< discard elements + } m_elem_res; + + //! true if any of the element resolution fields are non-zero + const bool isElemForRes() const { + return (m_elem_res.P0_commit || m_elem_res.P0_cancel || + m_elem_res.mispredict || m_elem_res.discard); + } + + void clearElemRes() { + m_elem_res.P0_commit = 0; + m_elem_res.P0_cancel = 0; + m_elem_res.mispredict = false; + m_elem_res.discard = false; + } + + // packet decode state + bool m_need_ctxt; //!< need context to continue + bool m_need_addr; //!< need an address to continue + bool m_elem_pending_addr; //!< next address packet is needed for prev element. + + ocsd_instr_info m_instr_info; //!< instruction info for code follower - in address is the next to be decoded. + + etmv4_trace_info_t m_trace_info; //!< trace info for this trace run. + + bool m_prev_overflow; + + TrcAddrReturnStack m_return_stack; //!< the address return stack. + +//** output element handling + OcsdGenElemStack m_out_elem; //!< output element stack. + OcsdTraceElement &outElem() { return m_out_elem.getCurrElem(); }; //!< current out element +}; + +#endif // ARM_TRC_PKT_DECODE_ETMV4I_H_INCLUDED + +/* End of File trc_pkt_decode_etmv4i.h */ diff --git a/decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4i.h b/decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4i.h new file mode 100644 index 0000000..22f39d9 --- /dev/null +++ b/decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4i.h @@ -0,0 +1,546 @@ +/* + * \file trc_pkt_elem_etmv4i.h + * \brief OpenCSD : + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ + + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ARM_TRC_PKT_ELEM_ETMV4I_H_INCLUDED +#define ARM_TRC_PKT_ELEM_ETMV4I_H_INCLUDED + +#include "trc_pkt_types_etmv4.h" +#include "common/trc_printable_elem.h" +#include "common/trc_pkt_elem_base.h" + +/** @addtogroup trc_pkts +@{*/ + +/*! +* @class Etmv4PktAddrStack +* @brief ETMv4 Address packet values stack +* @ingroup trc_pkts +* +* This class represents a stack of recent broadcast address values - +* used to fulfil the ExactMatch address type where no address is output. +* +*/ +class Etmv4PktAddrStack +{ +public: + Etmv4PktAddrStack() + { + reset_stack(); + } + ~Etmv4PktAddrStack() {}; + + void push(const ocsd_pkt_vaddr vaddr, const uint8_t isa) + { + m_v_addr[2] = m_v_addr[1]; + m_v_addr[1] = m_v_addr[0]; + m_v_addr[0] = vaddr; + m_v_addr_ISA[2] = m_v_addr_ISA[1]; + m_v_addr_ISA[1] = m_v_addr_ISA[0]; + m_v_addr_ISA[0] = isa; + } + + void get_idx(const uint8_t idx, ocsd_pkt_vaddr &vaddr, uint8_t &isa) + { + if (idx < 3) + { + vaddr = m_v_addr[idx]; + isa = m_v_addr_ISA[idx]; + } + } + + // explicit reset for TInfo. + void reset_stack() + { + for (int i = 0; i < 3; i++) + { + m_v_addr[i].pkt_bits = 0; + m_v_addr[i].size = OCSD_MAX_VA_BITSIZE == 64 ? VA_64BIT : VA_32BIT; + m_v_addr[i].val = 0; + m_v_addr[i].valid_bits = OCSD_MAX_VA_BITSIZE; + m_v_addr_ISA[i] = 0; + } + + } + +private: + ocsd_pkt_vaddr m_v_addr[3]; //!< most recently broadcast address packet + uint8_t m_v_addr_ISA[3]; +}; + +/*! + * @class EtmV4ITrcPacket + * @brief ETMv4 Instuction Trace Protocol Packet. + * @ingroup trc_pkts + * + * This class represents a single ETMv4 data trace packet, along with intra packet state. + * + */ +class EtmV4ITrcPacket : public TrcPacketBase, public ocsd_etmv4_i_pkt, public trcPrintableElem +{ +public: + EtmV4ITrcPacket(); + ~EtmV4ITrcPacket(); + + EtmV4ITrcPacket &operator =(const ocsd_etmv4_i_pkt* p_pkt); + + virtual const void *c_pkt() const { return (const ocsd_etmv4_i_pkt *)this; }; + + // update interface - set packet values + void initStartState(); //!< Set to initial state - no intra packet state valid. Use on start of trace / discontinuities. + void initNextPacket(); //!< clear any single packet only flags / state. + + void setType(const ocsd_etmv4_i_pkt_type pkt_type) { type = pkt_type; }; + void updateErrType(const ocsd_etmv4_i_pkt_type err_pkt_type, const uint8_t val = 0); + + void clearTraceInfo(); //!< clear all the trace info data prior to setting for new trace info packet. + void setTraceInfo(const uint32_t infoVal); + void setTraceInfoKey(const uint32_t keyVal); + void setTraceInfoSpec(const uint32_t specVal); + void setTraceInfoCyct(const uint32_t cyctVal); + + void setTS(const uint64_t value, const uint8_t bits); + void setCycleCount(const uint32_t value); + void setCommitElements(const uint32_t commit_elem); + void setCancelElements(const uint32_t cancel_elem); + void setAtomPacket(const ocsd_pkt_atm_type type, const uint32_t En_bits, const uint8_t num); + + void setCondIF1(uint32_t const cond_key); + void setCondIF2(uint8_t const c_elem_idx); + void setCondIF3(uint8_t const num_c_elem, const bool finalElem); + + void setCondRF1(const uint32_t key[2], const uint8_t res[2], const uint8_t CI[2], const bool set2Keys); + void setCondRF2(const uint8_t key_incr, const uint8_t token); + void setCondRF3(const uint16_t tokens); + void setCondRF4(const uint8_t token); + + void setContextInfo(const bool update, const uint8_t EL = 0, const uint8_t NS = 0, const uint8_t SF = 0, const uint8_t NSE = 0); + void setContextVMID(const uint32_t VMID); + void setContextCID(const uint32_t CID); + + void setExceptionInfo(const uint16_t excep_type, const uint8_t addr_interp, const uint8_t m_fault_pending, const uint8_t m_type); + + void set64BitAddress(const uint64_t addr, const uint8_t IS); + void set32BitAddress(const uint32_t addr, const uint8_t IS); + void updateShortAddress(const uint32_t addr, const uint8_t IS, const uint8_t update_bits); + void setAddressExactMatch(const uint8_t idx); + + void setDataSyncMarker(const uint8_t dsm_val); + void setEvent(const uint8_t event_val); + + void setQType(const bool has_count, const uint32_t count, const bool has_addr, const bool addr_match, const uint8_t type); + + // packet status interface - get packet info. + const ocsd_etmv4_i_pkt_type getType() const { return type; }; + const ocsd_etmv4_i_pkt_type getErrType() const { return err_type; }; + + //! return true if this packet has set the commit packet count. + const bool hasCommitElementsCount() const + { + return pkt_valid.bits.commit_elem_valid ? true : false; + }; + + // trace info + const etmv4_trace_info_t &getTraceInfo() const { return trace_info; }; + const uint32_t getCCThreshold() const; + const uint32_t getP0Key() const; + const uint32_t getCurrSpecDepth() const; + + // atom + const ocsd_pkt_atom &getAtom() const { return atom; }; + const int getNumAtoms() const { return atom.num; }; + + // context + const etmv4_context_t &getContext() const { return context; }; + + // address + const uint8_t &getAddrMatch() const { return addr_exact_match_idx; }; + const ocsd_vaddr_t &getAddrVal() const { return v_addr.val; }; + const uint8_t &getAddrIS() const { return v_addr_ISA; }; + const bool getAddr64Bit() const { return v_addr.size == VA_64BIT; }; + + // ts + const uint64_t getTS() const { return pkt_valid.bits.ts_valid ? ts.timestamp : 0; }; + + // cc + const uint32_t getCC() const { return pkt_valid.bits.cc_valid ? cycle_count : 0; }; + + // speculation + const int getCommitElem() const { return commit_elements; }; + const int getCancelElem() const { return cancel_elements; }; + + // packet type + const bool isBadPacket() const; + + // printing + virtual void toString(std::string &str) const; + virtual void toStringFmt(const uint32_t fmtFlags, std::string &str) const; + + void setProtocolVersion(const uint8_t version) { protocol_version = version; }; + +private: + const char *packetTypeName(const ocsd_etmv4_i_pkt_type type, const char **pDesc) const; + void contextStr(std::string &ctxtStr) const; + void atomSeq(std::string &valStr) const; + void addrMatchIdx(std::string &valStr) const; + void exceptionInfo(std::string &valStr) const; + + void push_vaddr(); + void pop_vaddr_idx(const uint8_t idx); + + const bool isETE() const { return (protocol_version & 0xF0) == 0x50; }; + + Etmv4PktAddrStack m_addr_stack; +}; + +inline void EtmV4ITrcPacket::updateErrType(const ocsd_etmv4_i_pkt_type err_pkt_type, const uint8_t err_val /* = 0 */) +{ + // set primary type to incoming error type, set packet err type to previous primary type. + err_type = type; + type = err_pkt_type; + err_hdr_val = err_val; +} + +inline void EtmV4ITrcPacket::clearTraceInfo() +{ + pkt_valid.bits.ts_valid = 0; + pkt_valid.bits.trace_info_valid = 0; + pkt_valid.bits.p0_key_valid = 0; + pkt_valid.bits.spec_depth_valid = 0; + pkt_valid.bits.cc_thresh_valid = 0; + + // set these as defaults - if they don't appear in TINFO this is the state. + setTraceInfo(0); + setTraceInfoSpec(0); + + // explicitly reset the stack & zero the current address. + m_addr_stack.reset_stack(); + m_addr_stack.get_idx(0, v_addr, v_addr_ISA); +} + +inline void EtmV4ITrcPacket::setTraceInfo(const uint32_t infoVal) +{ + trace_info.val = infoVal; + pkt_valid.bits.trace_info_valid = 1; +} + +inline void EtmV4ITrcPacket::setTraceInfoKey(const uint32_t keyVal) +{ + p0_key = keyVal; + pkt_valid.bits.p0_key_valid = 1; +} + +inline void EtmV4ITrcPacket::setTraceInfoSpec(const uint32_t specVal) +{ + curr_spec_depth = specVal; + pkt_valid.bits.spec_depth_valid = 1; +} + +inline void EtmV4ITrcPacket::setTraceInfoCyct(const uint32_t cyctVal) +{ + cc_threshold = cyctVal; + pkt_valid.bits.cc_thresh_valid = 1; +} + +inline void EtmV4ITrcPacket::setTS(const uint64_t value, const uint8_t bits) +{ + uint64_t mask = (uint64_t)-1LL; + if(bits < 64) mask = (1ULL << bits) - 1; + ts.timestamp = (ts.timestamp & ~mask) | (value & mask); + ts.bits_changed = bits; + pkt_valid.bits.ts_valid = 1; +} + +inline void EtmV4ITrcPacket::setCycleCount(const uint32_t value) +{ + pkt_valid.bits.cc_valid = 1; + cycle_count = value; +} + +inline void EtmV4ITrcPacket::setCommitElements(const uint32_t commit_elem) +{ + pkt_valid.bits.commit_elem_valid = 1; + commit_elements = commit_elem; +} + +inline const uint32_t EtmV4ITrcPacket::getCCThreshold() const +{ + if(pkt_valid.bits.cc_thresh_valid) + return cc_threshold; + return 0; +} + +inline const uint32_t EtmV4ITrcPacket::getP0Key() const +{ + if(pkt_valid.bits.p0_key_valid) + return p0_key; + return 0; +} + +inline const uint32_t EtmV4ITrcPacket::getCurrSpecDepth() const +{ + if(pkt_valid.bits.spec_depth_valid) + return curr_spec_depth; + return 0; +} + +inline void EtmV4ITrcPacket::setCancelElements(const uint32_t cancel_elem) +{ + cancel_elements = cancel_elem; +} + +inline void EtmV4ITrcPacket::setAtomPacket(const ocsd_pkt_atm_type type, const uint32_t En_bits, const uint8_t num) +{ + if(type == ATOM_REPEAT) + { + uint32_t bit_patt = En_bits & 0x1; + if(bit_patt) + { + // none zero - all 1s + bit_patt = (bit_patt << num) - 1; + } + atom.En_bits = bit_patt; + } + else + atom.En_bits = En_bits; + atom.num = num; +} + +inline void EtmV4ITrcPacket::setCondIF1(const uint32_t cond_key) +{ + cond_instr.cond_key_set = 1; + cond_instr.f3_final_elem = 0; + cond_instr.f2_cond_incr = 0; + cond_instr.num_c_elem = 1; + cond_instr.cond_c_key = cond_key; +} + +inline void EtmV4ITrcPacket::setCondIF2(const uint8_t c_elem_idx) +{ + cond_instr.cond_key_set = 0; + cond_instr.f3_final_elem = 0; + switch(c_elem_idx & 0x3) + { + case 0: + cond_instr.f2_cond_incr = 1; + cond_instr.num_c_elem = 1; + break; + + case 1: + cond_instr.f2_cond_incr = 0; + cond_instr.num_c_elem = 1; + break; + + case 2: + cond_instr.f2_cond_incr = 1; + cond_instr.num_c_elem = 2; + break; + } +} + +inline void EtmV4ITrcPacket::setCondIF3(const uint8_t num_c_elem, const bool finalElem) +{ + cond_instr.cond_key_set = 0; + cond_instr.f3_final_elem = finalElem ? 1: 0; + cond_instr.f2_cond_incr = 0; + cond_instr.num_c_elem = num_c_elem; +} + +inline void EtmV4ITrcPacket::setCondRF1(const uint32_t key[2], const uint8_t res[2], const uint8_t CI[2],const bool set2Keys) +{ + cond_result.key_res_0_set = 1; + cond_result.cond_r_key_0 = key[0]; + cond_result.res_0 = res[0]; + cond_result.ci_0 = CI[0]; + + if(set2Keys) + { + cond_result.key_res_1_set = 1; + cond_result.cond_r_key_1 = key[1]; + cond_result.res_1 = res[1]; + cond_result.ci_1 = CI[1]; + } +} + + +inline void EtmV4ITrcPacket::setCondRF2(const uint8_t key_incr, const uint8_t token) +{ + cond_result.key_res_0_set = 0; + cond_result.key_res_1_set = 0; + cond_result.f2_key_incr = key_incr; + cond_result.f2f4_token = token; +} + +inline void EtmV4ITrcPacket::setCondRF3(const uint16_t tokens) +{ + cond_result.key_res_0_set = 0; + cond_result.key_res_1_set = 0; + cond_result.f3_tokens = tokens; +} + +inline void EtmV4ITrcPacket::setCondRF4(const uint8_t token) +{ + cond_result.key_res_0_set = 0; + cond_result.key_res_1_set = 0; + cond_result.f2f4_token = token; +} + +inline void EtmV4ITrcPacket::setContextInfo(const bool update, const uint8_t EL, const uint8_t NS, const uint8_t SF, const uint8_t NSE) +{ + pkt_valid.bits.context_valid = 1; + if(update) + { + context.updated = 1; + context.EL = EL; + context.NS = NS; + context.SF = SF; + context.NSE = NSE; + } +} + +inline void EtmV4ITrcPacket::setContextVMID(const uint32_t VMID) +{ + pkt_valid.bits.context_valid = 1; + context.updated = 1; + context.VMID = VMID; + context.updated_v = 1; +} + +inline void EtmV4ITrcPacket::setContextCID(const uint32_t CID) +{ + pkt_valid.bits.context_valid = 1; + context.updated = 1; + context.ctxtID = CID; + context.updated_c = 1; +} + +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) +{ + exception_info.exceptionType = excep_type; + exception_info.addr_interp = addr_interp; + exception_info.m_fault_pending = m_fault_pending; + exception_info.m_type = m_type; +} + +inline void EtmV4ITrcPacket::set64BitAddress(const uint64_t addr, const uint8_t IS) +{ + v_addr.pkt_bits = 64; + v_addr.valid_bits = 64; + v_addr.size = VA_64BIT; + v_addr.val = addr; + v_addr_ISA = IS; + push_vaddr(); +} + +inline void EtmV4ITrcPacket::set32BitAddress(const uint32_t addr, const uint8_t IS) +{ + uint64_t mask = OCSD_BIT_MASK(32); + v_addr.pkt_bits = 32; + + if (pkt_valid.bits.context_valid && context.SF) + { + v_addr.size = VA_64BIT; + v_addr.val = (v_addr.val & ~mask) | (addr & mask); + } + else + { + v_addr.val = addr; + v_addr.size = VA_32BIT; + } + + if (v_addr.valid_bits < 32) // may be updating a 64 bit address so only set 32 if currently less. + v_addr.valid_bits = 32; + + v_addr_ISA = IS; + push_vaddr(); +} + +inline void EtmV4ITrcPacket::updateShortAddress(const uint32_t addr, const uint8_t IS, const uint8_t update_bits) +{ + ocsd_vaddr_t update_mask = OCSD_BIT_MASK(update_bits); + v_addr.pkt_bits = update_bits; + if(v_addr.valid_bits < update_bits) + v_addr.valid_bits = update_bits; + + v_addr.val = (v_addr.val & ~update_mask) | (addr & update_mask); + v_addr_ISA = IS; + push_vaddr(); +} + +inline void EtmV4ITrcPacket::setAddressExactMatch(const uint8_t idx) +{ + addr_exact_match_idx = idx; + pop_vaddr_idx(idx); + push_vaddr(); +} + +inline void EtmV4ITrcPacket::setDataSyncMarker(const uint8_t dsm_value) +{ + dsm_val = dsm_value; +} + +inline void EtmV4ITrcPacket::setEvent(const uint8_t event_value) +{ + event_val = event_value; +} + +inline void EtmV4ITrcPacket::setQType(const bool has_count, const uint32_t count, const bool has_addr, const bool addr_match, const uint8_t type) +{ + Q_pkt.q_count = count; + Q_pkt.q_type = type; + Q_pkt.count_present = has_count ? 1 : 0; + Q_pkt.addr_present = has_addr ? 1: 0; + Q_pkt.addr_match = addr_match ? 1 :0; +} + +inline const bool EtmV4ITrcPacket::isBadPacket() const +{ + return (type >= ETM4_PKT_I_BAD_SEQUENCE); +} + +inline void EtmV4ITrcPacket::push_vaddr() +{ + m_addr_stack.push(v_addr, v_addr_ISA); +} + +inline void EtmV4ITrcPacket::pop_vaddr_idx(const uint8_t idx) +{ + m_addr_stack.get_idx(idx, v_addr, v_addr_ISA); +} + +/** @}*/ + +#endif // ARM_TRC_PKT_ELEM_ETMV4I_H_INCLUDED + +/* End of File trc_pkt_elem_etmv4i.h */ diff --git a/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4.h b/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4.h new file mode 100644 index 0000000..25bdf51 --- /dev/null +++ b/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4.h @@ -0,0 +1,47 @@ +/* + * \file trc_pkt_proc_etmv4.h + * \brief OpenCSD : ETMv4 packet processor interface classes. + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ARM_TRC_PKT_PROC_ETMV4_H_INCLUDED +#define ARM_TRC_PKT_PROC_ETMV4_H_INCLUDED + +// split I & D into separate files, retain this header for backward compatibility +// for now just include the I packet processor as that is the only one implemented. + +#include "trc_pkt_types_etmv4.h" +#include "trc_pkt_proc_etmv4i.h" +#include "common/trc_pkt_proc_base.h" + +#endif // ARM_TRC_PKT_PROC_ETMV4_H_INCLUDED + +/* End of File trc_pkt_proc_etmv4.h */ diff --git a/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4i.h b/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4i.h new file mode 100644 index 0000000..19388c3 --- /dev/null +++ b/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4i.h @@ -0,0 +1,215 @@ +/* + * \file trc_pkt_proc_etmv4i.h + * \brief OpenCSD : Implementation of ETMv4 packet processing + * + * \copyright Copyright (c) 2015, 2019 ARM Limited. All Rights Reserved. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ARM_TRC_PKT_PROC_ETMV4I_IMPL_H_INCLUDED +#define ARM_TRC_PKT_PROC_ETMV4I_IMPL_H_INCLUDED + +#include "trc_pkt_types_etmv4.h" +#include "opencsd/etmv4/trc_pkt_proc_etmv4.h" +#include "opencsd/etmv4/trc_cmp_cfg_etmv4.h" +#include "opencsd/etmv4/trc_pkt_elem_etmv4i.h" +#include "common/trc_raw_buffer.h" +#include "common/trc_pkt_proc_base.h" + +class EtmV4ITrcPacket; +class EtmV4Config; + +/** @addtogroup ocsd_pkt_proc +@{*/ + +class TrcPktProcEtmV4I : public TrcPktProcBase< EtmV4ITrcPacket, ocsd_etmv4_i_pkt_type, EtmV4Config> +{ +public: + TrcPktProcEtmV4I(); + TrcPktProcEtmV4I(int instIDNum); + virtual ~TrcPktProcEtmV4I(); + +protected: + /* implementation packet processing interface */ + virtual ocsd_datapath_resp_t processData( const ocsd_trc_index_t index, + const uint32_t dataBlockSize, + const uint8_t *pDataBlock, + uint32_t *numBytesProcessed); + virtual ocsd_datapath_resp_t onEOT(); + virtual ocsd_datapath_resp_t onReset(); + virtual ocsd_datapath_resp_t onFlush(); + virtual ocsd_err_t onProtocolConfig(); + virtual const bool isBadPacket() const; + +protected: + typedef enum _process_state { + PROC_HDR, + PROC_DATA, + SEND_PKT, + SEND_UNSYNCED, + PROC_ERR, + } process_state; + + process_state m_process_state; + + void InitPacketState(); // clear current packet state. + void InitProcessorState(); // clear all previous process state + + /** packet processor configuration **/ + bool m_isInit; + + // etmv4 hardware configuration + EtmV4Config m_config; + + /** packet data **/ + TraceRawBuffer m_trcIn; // trace data in buffer + std::vector<uint8_t> m_currPacketData; // raw data packet + int m_currPktIdx; // index into raw packet when expanding + EtmV4ITrcPacket m_curr_packet; // expanded packet + ocsd_trc_index_t m_packet_index; // index of the start of the current packet + ocsd_trc_index_t m_blockIndex; // index at the start of the current data block being processed + + // searching for sync + bool m_is_sync; //!< seen first sync packet + bool m_first_trace_info; //!< seen first trace info packet after sync + bool m_sent_notsync_packet; //!< send one not sync packet if we see any unsynced data on the channel + unsigned m_dump_unsynced_bytes; //!< number of unsynced bytes to send + ocsd_trc_index_t m_update_on_unsync_packet_index; + + +private: + // current processing state data - counts and flags to determine if a packet is complete. + + // TraceInfo Packet + // flags to indicate processing progress for these sections is complete. + struct _t_info_pkt_prog { + uint8_t sectFlags; + uint8_t ctrlBytes; + } m_tinfo_sections; + + #define TINFO_INFO_SECT 0x01 + #define TINFO_KEY_SECT 0x02 + #define TINFO_SPEC_SECT 0x04 + #define TINFO_CYCT_SECT 0x08 + #define TINFO_WNDW_SECT 0x10 + #define TINFO_CTRL 0x20 + #define TINFO_ALL_SECT 0x1F + #define TINFO_ALL 0x3F + + + // address and context packets + int m_addrBytes; + uint8_t m_addrIS; + bool m_bAddr64bit; + int m_vmidBytes; // bytes still to find + int m_ctxtidBytes; // bytes still to find + bool m_bCtxtInfoDone; + bool m_addr_done; + + // timestamp + bool m_ccount_done; // done or not needed + bool m_ts_done; + int m_ts_bytes; + + // exception + int m_excep_size; + + // cycle count + bool m_has_count; + bool m_count_done; + bool m_commit_done; + + // cond result + bool m_F1P1_done; // F1 payload 1 done + bool m_F1P2_done; // F1 payload 2 done + bool m_F1has_P2; // F1 has a payload 2 + + // Q packets (use some from above too) + bool m_has_addr; + bool m_addr_short; + bool m_addr_match; + uint8_t m_Q_type; + uint8_t m_QE; + + ocsd_datapath_resp_t outputPacket(); + ocsd_datapath_resp_t outputUnsyncedRawPacket(); + + void iNotSync(const uint8_t lastByte); // not synced yet + void iPktNoPayload(const uint8_t lastByte); // process a single byte packet + void iPktReserved(const uint8_t lastByte); // deal with reserved header value + void iPktExtension(const uint8_t lastByte); + void iPktASync(const uint8_t lastByte); + void iPktTraceInfo(const uint8_t lastByte); + void iPktTimestamp(const uint8_t lastByte); + void iPktException(const uint8_t lastByte); + void iPktCycleCntF123(const uint8_t lastByte); + void iPktSpeclRes(const uint8_t lastByte); + void iPktCondInstr(const uint8_t lastByte); + void iPktCondResult(const uint8_t lastByte); + void iPktContext(const uint8_t lastByte); + void iPktAddrCtxt(const uint8_t lastByte); + void iPktShortAddr(const uint8_t lastByte); + void iPktLongAddr(const uint8_t lastByte); + void iPktQ(const uint8_t lastByte); + void iAtom(const uint8_t lastByte); + void iPktInvalidCfg(const uint8_t lastByte); // packet invalid in current config. + + unsigned extractContField(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint32_t &value, const unsigned byte_limit = 5); + unsigned extractTSField64(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint64_t &value); + unsigned extractCondResult(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint32_t& key, uint8_t &result); + void extractAndSetContextInfo(const std::vector<uint8_t> &buffer, const int st_idx); + int extract64BitLongAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint64_t &value); + int extract32BitLongAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint32_t &value); + int extractShortAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint32_t &value, int &bits); + + // packet processing is table driven. + typedef void (TrcPktProcEtmV4I::*PPKTFN)(uint8_t); + PPKTFN m_pIPktFn; + + struct _pkt_i_table_t { + ocsd_etmv4_i_pkt_type pkt_type; + PPKTFN pptkFn; + } m_i_table[256]; + + void BuildIPacketTable(); + + void throwBadSequenceError(const char *pszExtMsg); +}; + + +inline const bool TrcPktProcEtmV4I::isBadPacket() const +{ + return m_curr_packet.isBadPacket(); +} + +/** @}*/ + +#endif // ARM_TRC_PKT_PROC_ETMV4I_IMPL_H_INCLUDED + +/* End of File trc_pkt_proc_etmv4i_impl.h */ diff --git a/decoder/include/opencsd/etmv4/trc_pkt_types_etmv4.h b/decoder/include/opencsd/etmv4/trc_pkt_types_etmv4.h new file mode 100644 index 0000000..38963d1 --- /dev/null +++ b/decoder/include/opencsd/etmv4/trc_pkt_types_etmv4.h @@ -0,0 +1,392 @@ +/* + * \file trc_pkt_types_etmv4.h + * \brief OpenCSD : ETMv4 / ETE packet info + * + * \copyright Copyright (c) 2015,2019 ARM Limited. All Rights Reserved. + */ + + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ARM_TRC_PKT_TYPES_ETMV4_H_INCLUDED +#define ARM_TRC_PKT_TYPES_ETMV4_H_INCLUDED + +#include "opencsd/trc_pkt_types.h" + +/** @addtogroup trc_pkts +@{*/ + +/** @name ETMv4 Packet Types, ETE packet Types +@{*/ + +/** I stream packets. */ +typedef enum _ocsd_etmv4_i_pkt_type +{ +/* state of decode markers */ + ETM4_PKT_I_NOTSYNC = 0x200, /*!< no sync found yet. */ + ETM4_PKT_I_INCOMPLETE_EOT, /*!< flushing incomplete/empty packet at end of trace.*/ + ETM4_PKT_I_NO_ERR_TYPE, /*!< error type not set for packet. */ + +/* markers for unknown/bad packets */ + ETM4_PKT_I_BAD_SEQUENCE = 0x300, /*!< invalid sequence for packet type. */ + ETM4_PKT_I_BAD_TRACEMODE, /*!< invalid packet type for this trace mode. */ + ETM4_PKT_I_RESERVED, /*!< packet type reserved. */ + ETM4_PKT_I_RESERVED_CFG, /*!< packet type reserved for current configuration */ + +/* I stream packet types. */ + /* extension header. */ + ETM4_PKT_I_EXTENSION = 0x00, /*!< b00000000 */ + + /* sync */ + ETM4_PKT_I_TRACE_INFO = 0x01, /*!< b00000001 */ + // timestamp + ETM4_PKT_I_TIMESTAMP = 0x02, /*!< b0000001x */ + ETM4_PKT_I_TRACE_ON = 0x04, /*!< b00000100 */ + ETM4_PKT_I_FUNC_RET = 0x05, /*!< b00000101 (V8M only) */ + // Exceptions + ETM4_PKT_I_EXCEPT = 0x06, /*!< b00000110 */ + ETM4_PKT_I_EXCEPT_RTN = 0x07, /*!< b00000111 (ETE invalid) */ + + /* unused encoding 0x08 b00001000 */ + ETE_PKT_I_COMMIT_WIN_MV = 0x09, /*! b00001001 (ETE only - unused in current versions) */ + ETE_PKT_I_TRANS_ST = 0x0A, /*! b00001010 (ETE only) */ + ETE_PKT_I_TRANS_COMMIT = 0x0B, /*! b00001011 (ETE only) */ + + /* cycle count packets */ + ETM4_PKT_I_CCNT_F2 = 0x0C, /*!< b0000110x */ + ETM4_PKT_I_CCNT_F1 = 0x0E, /*!< b0000111x */ + ETM4_PKT_I_CCNT_F3 = 0x10, /*!< b0001xxxx */ + + // data synchronisation markers + ETM4_PKT_I_NUM_DS_MKR = 0x20, /*!< b00100xxx */ + ETM4_PKT_I_UNNUM_DS_MKR = 0x28, /*!< b00101000 to b00101100 0x2C */ + + // speculation + ETM4_PKT_I_COMMIT = 0x2D, /*!< b00101101 */ + ETM4_PKT_I_CANCEL_F1 = 0x2E, /*!< b00101110 */ + ETM4_PKT_I_CANCEL_F1_MISPRED = 0x2F, /*!< b00101111 */ + ETM4_PKT_I_MISPREDICT = 0x30, /*!< b001100xx */ + ETM4_PKT_I_CANCEL_F2 = 0x34, /*!< b001101xx */ + ETM4_PKT_I_CANCEL_F3 = 0x38, /*!< b00111xxx */ + + /* conditional instruction tracing - (reserved encodings ETE) */ + ETM4_PKT_I_COND_I_F2 = 0x40, /*!< b01000000 - b01000010 */ + ETM4_PKT_I_COND_FLUSH = 0x43, /*!< b01000011 */ + ETM4_PKT_I_COND_RES_F4 = 0x44, /*!< b0100010x, b01000110 */ + /* unused encoding 0x47 b01000111 */ + ETM4_PKT_I_COND_RES_F2 = 0x48, /*!< b0100100x, b01001010, b0100110x, b01001110 */ + /* unused encodings 0x4B,0x4F b01001011, b01001111 */ + ETM4_PKT_I_COND_RES_F3 = 0x50, /*!< b0101xxxx */ + /* unused encodings 0x60-0x67 b01100xxx */ + ETM4_PKT_I_COND_RES_F1 = 0x68, /*!< b011010xx, b0110111x 0x68-0x6B, 0x6e-0x6F */ + ETM4_PKT_I_COND_I_F1 = 0x6C, /*!< b01101100 */ + ETM4_PKT_I_COND_I_F3 = 0x6D, /*!< b01101101 */ + + // event trace + ETM4_PKT_I_IGNORE = 0x70, /*!< b01110000 */ + ETM4_PKT_I_EVENT = 0x71, /*!< b01110001 to 0x01111111 0x7F */ + + /* address and context */ + ETM4_PKT_I_CTXT = 0x80, /*!< b1000000x */ + ETM4_PKT_I_ADDR_CTXT_L_32IS0 = 0x82, /*!< b10000010 */ + ETM4_PKT_I_ADDR_CTXT_L_32IS1, /*!< b10000011 */ + /* unused encoding 0x84 b10000100 */ + ETM4_PKT_I_ADDR_CTXT_L_64IS0 = 0x85, /*!< b10000101 */ + ETM4_PKT_I_ADDR_CTXT_L_64IS1, /*!< b10000110 */ + /* unused encoding 0x87 b10000111 */ + ETE_PKT_I_TS_MARKER = 0x88, /*!< b10001000 */ + /* unused encodings 0x89-0x8F b10001001 to b10001111 */ + ETM4_PKT_I_ADDR_MATCH = 0x90, /*!< b10010000 to b10010010 0x92 */ + /* unused encodings 0x93-0x94 b10010011 to b10010010 */ + ETM4_PKT_I_ADDR_S_IS0 = 0x95, /*!< b10010101 */ + ETM4_PKT_I_ADDR_S_IS1, /*!< b10010110 */ + /* unused encodings 0x97 b10010111 to b10011001 0x99 */ + ETM4_PKT_I_ADDR_L_32IS0 = 0x9A, /*!< b10011010 */ + ETM4_PKT_I_ADDR_L_32IS1, /*!< b10011011 */ + /* unused encoding 0x9C b10011100 */ + ETM4_PKT_I_ADDR_L_64IS0 = 0x9D, /*!< b10011101 */ + ETM4_PKT_I_ADDR_L_64IS1, /*!< b10011110 */ + /* unused encoding 0x9F b10011111 */ + + /* Q packets */ + ETM4_PKT_I_Q = 0xA0, /*!< b1010xxxx */ + + /* ETE source address packets, unused ETMv4 */ + ETE_PKT_I_SRC_ADDR_MATCH = 0xB0, /*!< b101100xx */ + ETE_PKT_I_SRC_ADDR_S_IS0 = 0xB4, /*!< b10110100 */ + ETE_PKT_I_SRC_ADDR_S_IS1 = 0xB5, /*!< b10110101 */ + ETE_PKT_I_SRC_ADDR_L_32IS0 = 0xB6, /*!< b10110110 */ + ETE_PKT_I_SRC_ADDR_L_32IS1 = 0xB7, /*!< b10110111 */ + ETE_PKT_I_SRC_ADDR_L_64IS0 = 0xB8, /*!< b10111000 */ + ETE_PKT_I_SRC_ADDR_L_64IS1 = 0xB9, /*!< b10111001 */ + /* unused encodings 0xBA-0xBF b10111010 - b10111111 */ + + /* Atom packets */ + ETM4_PKT_I_ATOM_F6 = 0xC0, /*!< b11000000 - b11010100 0xC0 - 0xD4, b11100000 - b11110100 0xE0 - 0xF4 */ + ETM4_PKT_I_ATOM_F5 = 0xD5, /*!< b11010101 - b11010111 0xD5 - 0xD7, b11110101 0xF5 */ + ETM4_PKT_I_ATOM_F2 = 0xD8, /*!< b110110xx to 0xDB */ + ETM4_PKT_I_ATOM_F4 = 0xDC, /*!< b110111xx to 0xDF */ + ETM4_PKT_I_ATOM_F1 = 0xF6, /*!< b1111011x to 0xF7 */ + ETM4_PKT_I_ATOM_F3 = 0xF8, /*!< b11111xxx to 0xFF */ + + // extension packets - follow 0x00 header + ETM4_PKT_I_ASYNC = 0x100, //!< b00000000 + ETM4_PKT_I_DISCARD = 0x103, //!< b00000011 + ETM4_PKT_I_OVERFLOW = 0x105, //!< b00000101 + + // ETE extended types + ETE_PKT_I_PE_RESET = 0x400, // base type is exception packet. + ETE_PKT_I_TRANS_FAIL = 0x401, // base type is exception packet. + +} ocsd_etmv4_i_pkt_type; + +typedef union _etmv4_trace_info_t { + uint32_t val; //!< trace info full value. + struct { + uint32_t cc_enabled:1; //!< 1 if cycle count enabled + uint32_t cond_enabled:3; //!< conditional trace enabled type. + uint32_t p0_load:1; //!< 1 if tracing with P0 load elements (for data trace) + uint32_t p0_store:1; //!< 1 if tracing with P0 store elements (for data trace) + uint32_t in_trans_state:1; //!< 1 if starting trace when in a transactional state (ETE trace). + } bits; //!< bitfields for trace info value. +} etmv4_trace_info_t; + +typedef struct _etmv4_context_t { + struct { + uint32_t EL:2; //!< exception level. + uint32_t SF:1; //!< sixty four bit + uint32_t NS:1; //!< none secure + uint32_t updated:1; //!< updated this context packet (otherwise same as last time) + uint32_t updated_c:1; //!< updated CtxtID + uint32_t updated_v:1; //!< updated VMID + uint32_t NSE:1; //!< PE FEAT_RME: root / realm indicator + }; + uint32_t ctxtID; //!< Current ctxtID + uint32_t VMID; //!< current VMID +} etmv4_context_t; + +/** a broadcast address value. */ +typedef struct _etmv4_addr_val_t { + ocsd_vaddr_t val; //!< Address value. + uint8_t isa; //!< instruction set. +} etmv4_addr_val_t; + +typedef struct _ocsd_etmv4_i_pkt +{ + ocsd_etmv4_i_pkt_type type; /**< Trace packet type derived from header byte */ + + //** intra-packet data - valid across packets. + + ocsd_pkt_vaddr v_addr; //!< most recently broadcast address packet + uint8_t v_addr_ISA; //!< ISA for the address packet. (0 = IS0 / 1 = IS1) + + etmv4_context_t context; //!< current context for PE + + struct { + uint64_t timestamp; //!< current timestamp value + uint8_t bits_changed; //!< bits updated in this timestamp packet. + } ts; + + uint32_t cc_threshold; //!< cycle count threshold - from trace info. + + // single packet data - only valid for specific packet types on packet instance. + ocsd_pkt_atom atom; //!< atom elements - number of atoms indicates validity of packet + uint32_t cycle_count; //!< cycle count + + uint32_t curr_spec_depth; //!< current speculation depth + uint32_t p0_key; //!< current P0 key value for data packet synchronisation + + uint32_t commit_elements; //<! commit elements indicated by this packet - valid dependent on the packet type. + uint32_t cancel_elements; //<! cancel elements indicated by this packet - valid dependent on the packet type. + + etmv4_trace_info_t trace_info; //!< trace info structure - programmed configuration of trace capture. + + struct { + uint32_t exceptionType:10; //!< exception number + uint32_t addr_interp:2; //!< address value interpretation + uint32_t m_fault_pending:1; //!< M class fault pending. + uint32_t m_type:1; //!< 1 if M class exception. + } exception_info; + + + uint8_t addr_exact_match_idx; //!< address match index in this packet. + uint8_t dsm_val; //!< Data Sync Marker number, or unnumbered atom count - packet type determines. + uint8_t event_val; //!< Event value on event packet. + + struct { + uint32_t cond_c_key; + uint8_t num_c_elem; + struct { + uint32_t cond_key_set:1; + uint32_t f3_final_elem:1; + uint32_t f2_cond_incr:1; + }; + } cond_instr; + + struct { + uint32_t cond_r_key_0; + uint32_t cond_r_key_1; + struct { + uint32_t res_0:4; + uint32_t res_1:4; + uint32_t ci_0:1; + uint32_t ci_1:1; + uint32_t key_res_0_set:1; + uint32_t key_res_1_set:1; + uint32_t f2_key_incr:2; + uint32_t f2f4_token:2; + uint32_t f3_tokens:12; + }; + } cond_result; + + struct { + uint32_t q_count; + struct { + uint32_t addr_present:1; + uint32_t addr_match:1; + uint32_t count_present:1; + uint32_t q_type:4; + }; + } Q_pkt; + + //! valid bits for packet elements (addresses have their own valid bits). + union { + uint32_t val; + struct { + uint32_t context_valid:1; + uint32_t ts_valid:1; + uint32_t spec_depth_valid:1; + uint32_t p0_key_valid:1; + uint32_t cond_c_key_valid:1; + uint32_t cond_r_key_valid:1; + uint32_t trace_info_valid:1; + uint32_t cc_thresh_valid:1; + uint32_t cc_valid:1; + uint32_t commit_elem_valid:1; + } bits; + } pkt_valid; + + // original header type when packet type changed to error on decode error. + ocsd_etmv4_i_pkt_type err_type; + uint8_t err_hdr_val; + + // protocol version - validity of ETE specific fields 0xMm == v Major.minor + uint8_t protocol_version; + +} ocsd_etmv4_i_pkt; + + +// D stream packets +typedef enum _ocsd_etmv4_d_pkt_type +{ +// markers for unknown/bad packets + ETM4_PKT_D_NOTSYNC = 0x200, //!< no sync found yet + ETM4_PKT_D_BAD_SEQUENCE, //!< invalid sequence for packet type + ETM4_PKT_D_BAD_TRACEMODE, //!< invalid packet type for this trace mode. + ETM4_PKT_D_RESERVED, //!< packet type reserved. + ETM4_PKT_D_INCOMPLETE_EOT, //!< flushing incomplete packet at end of trace. + ETM4_PKT_D_NO_HEADER, //!< waiting for a header byte + ETM4_PKT_D_NO_ERR_TYPE, //!< error packet has no header based type. Use with unknown/res packet types. + + // data sync markers + ETM4_PKT_DNUM_DS_MKR = 0x111, // ext packet, b0001xxx1 + // extension header + ETM4_PKT_D_EXTENSION = 0x00, //!< b00000000 + + ETM4_PKT_DUNNUM_DS_MKR = 0x01, //!< b00000001 + // event trace + ETM4_PKT_DEVENT = 0x04, //!< b00000100 + // timestamp + ETM4_PKT_DTIMESTAMP = 0x02, //!< b00000010 + // P1 Data address + ETM4_PKT_DADDR_P1_F1 = 0x70, //!< b0111xxxx + ETM4_PKT_DADDR_P1_F2 = 0x80, //!< b10xxxxxx + ETM4_PKT_DADDR_P1_F3 = 0x14, //!< b000101xx + ETM4_PKT_DADDR_P1_F4 = 0x60, //!< b0110xxxx + ETM4_PKT_DADDR_P1_F5 = 0xF8, //!< b11111xxx + ETM4_PKT_DADDR_P1_F6 = 0xF6, //!< b1111011x + ETM4_PKT_DADDR_P1_F7 = 0xF5, //!< b11110101 + // P2 Data value + ETM4_PKT_DVAL_P2_F1 = 0x20, //!< b0010xxxx + ETM4_PKT_DVAL_P2_F2 = 0x30, //!< b00110xxx + ETM4_PKT_DVAL_P2_F3 = 0x40, //!< b010xxxxx + ETM4_PKT_DVAL_P2_F4 = 0x10, //!< b000100xx + ETM4_PKT_DVAL_P2_F5 = 0x18, //!< b00011xxx + ETM4_PKT_DVAL_P2_F6 = 0x38, //!< b00111xxx + // suppression + ETM4_PKT_DSUPPRESSION = 0x03, //!< b00000011 + // synchronisation- extension packets - follow 0x00 header + ETM4_PKT_DTRACE_INFO = 0x101, //!< b00000001 + + // extension packets - follow 0x00 header + ETM4_PKT_D_ASYNC = 0x100, //!< b00000000 + ETM4_PKT_D_DISCARD = 0x103, //!< b00000011 + ETM4_PKT_D_OVERFLOW = 0x105 //!< b00000101 + +} ocsd_etmv4_d_pkt_type; + + +typedef struct _ocsd_etmv4_d_pkt +{ + ocsd_etmv4_d_pkt_type type; + + ocsd_pkt_vaddr d_addr; + + uint64_t pkt_val; /**< Packet value -> data value, timestamp value, event value */ + + ocsd_etmv4_d_pkt_type err_type; + +} ocsd_etmv4_d_pkt; + +typedef struct _ocsd_etmv4_cfg +{ + uint32_t reg_idr0; /**< ID0 register */ + uint32_t reg_idr1; /**< ID1 register */ + uint32_t reg_idr2; /**< ID2 register */ + uint32_t reg_idr8; + uint32_t reg_idr9; + uint32_t reg_idr10; + uint32_t reg_idr11; + uint32_t reg_idr12; + uint32_t reg_idr13; + uint32_t reg_configr; /**< Config Register */ + uint32_t reg_traceidr; /**< Trace Stream ID register */ + ocsd_arch_version_t arch_ver; /**< Architecture version */ + ocsd_core_profile_t core_prof; /**< Core Profile */ +} ocsd_etmv4_cfg; + +#define ETE_ARCH_VERSION 0x5 + +#define ETE_OPFLG_PKTDEC_SRCADDR_N_ATOMS 0x00010000 /**< Split source address output ranges for N-atoms */ + +/** @}*/ +/** @}*/ +#endif // ARM_TRC_PKT_TYPES_ETMV4_H_INCLUDED + +/* End of File trc_pkt_types_etmv4.h */ + |