Import OpenCSD v.1.4.0.

Sponsored by:	UKRI
This commit is contained in:
Ruslan Bukin 2023-03-27 17:03:16 +01:00
commit 46e6e29097
51 changed files with 2210 additions and 356 deletions

View File

@ -80,16 +80,16 @@ public:
private:
ocsd_trace_protocol_t m_builtInProtocol; //!< Protocol ID if built in type.
const ocsd_trace_protocol_t m_builtInProtocol; //!< Protocol ID if built in type.
};
template <class P, class Pt, class Pc>
DecoderMngrBase<P,Pt,Pc>::DecoderMngrBase(const std::string &decoderTypeName, ocsd_trace_protocol_t builtInProtocol)
DecoderMngrBase<P,Pt,Pc>::DecoderMngrBase(const std::string &decoderTypeName, ocsd_trace_protocol_t builtInProtocol) :
m_builtInProtocol(builtInProtocol)
{
OcsdLibDcdRegister *pDcdReg = OcsdLibDcdRegister::getDecoderRegister();
if(pDcdReg)
pDcdReg->registerDecoderTypeByName(decoderTypeName,this);
m_builtInProtocol = builtInProtocol;
}
template <class P, class Pt, class Pc>
@ -362,6 +362,49 @@ public:
}
};
/* full decode - extended config object - base + derived. */
template< class P, // Packet class.
class Pt, // Packet enum type ID.
class Pc, // Processor config base class.
class PcEx, // Processor config derived class
class PcSt, // Processor config struct type
class PktProc, // Packet processor class.
class PktDcd> // Packet decoder class.
class DecodeMngrFullDcdExCfg : public DecoderMngrBase<P, Pt, Pc>
{
public:
DecodeMngrFullDcdExCfg(const std::string &name, ocsd_trace_protocol_t builtInProtocol)
: DecoderMngrBase<P, Pt, Pc>(name, builtInProtocol) {};
virtual ~DecodeMngrFullDcdExCfg() {};
virtual TraceComponent *createPktProc(const bool useInstID, const int instID)
{
TraceComponent *pComp;
if (useInstID)
pComp = new (std::nothrow) PktProc(instID);
else
pComp = new (std::nothrow) PktProc();
return pComp;
}
virtual TraceComponent *createPktDecode(const bool useInstID, const int instID)
{
TraceComponent *pComp;
if (useInstID)
pComp = new (std::nothrow)PktDcd(instID);
else
pComp = new (std::nothrow)PktDcd();
return pComp;
}
virtual CSConfig *createConfig(const void *pDataStruct)
{
return new (std::nothrow) PcEx((PcSt *)pDataStruct);
}
};
/****************************************************************************************************/
/* Packet processor only, templated base for creating decoder objects */
/****************************************************************************************************/

View File

@ -168,6 +168,30 @@ public:
*/
ocsd_err_t removeDecoder(const uint8_t CSID);
/*!
* Get the stats block for the channel indicated.
* Caller must check p_stats_block->version to esure that the block
* is filled in a compatible manner.
*
* @param CSID : Configured CoreSight trace ID for the decoder.
* @param p_stats_block: block pointer to set to reference the stats block.
*
* @return ocsd_err_t : Library error code - OCSD_OK if valid block pointer returned,
* OCSD_ERR_NOTINIT if decoder does not support stats counting.
*/
ocsd_err_t getDecoderStats(const uint8_t CSID, ocsd_decode_stats_t **p_stats_block);
/*!
* Reset the stats block for the chosens decode channel.
* stats block is reset independently of the decoder reset to allow counts across
* multiple decode runs.
*
* @param handle : Handle to decode tree.
* @param CSID : Configured CoreSight trace ID for the decoder.
*
* @return ocsd_err_t : Library error code - OCSD_OK if successful.
*/
ocsd_err_t resetDecoderStats(const uint8_t CSID);
/* get decoder elements currently in use */
@ -387,7 +411,7 @@ private:
void destroyMemAccMapper();
ocsd_err_t initCallbackMemAcc(const ocsd_vaddr_t st_address, const ocsd_vaddr_t en_address,
const ocsd_mem_space_acc_t mem_space, void *p_cb_func, bool IDfn, const void *p_context);
TrcPktProcI *getPktProcI(const uint8_t CSID);
ocsd_dcd_tree_src_t m_dcd_tree_type;
@ -417,6 +441,9 @@ private:
/**! default instruction decoder */
static TrcIDecode s_instruction_decoder;
/**! demux stats block */
ocsd_demux_stats_t m_demux_stats;
};
/** @}*/

View File

@ -108,6 +108,17 @@ inline ocsdError& ocsdError::operator=(const ocsdError &err)
return (*this = &err);
}
/* class to get data path response values as strings */
class ocsdDataRespStr
{
public:
ocsdDataRespStr(ocsd_datapath_resp_t type) { m_type = type; }
~ocsdDataRespStr() {};
const char* getStr();
private:
ocsd_datapath_resp_t m_type;
};
/** @}*/

View File

@ -53,7 +53,8 @@
*
* Valid architecture profile names are:-
* - ARMv7-A, ARMv7-R, ARMv7-M;
* - ARMv8-A, ARMv8.3A, ARMv8-R, ARMv8-M;
* - ARMv8-A, ARMv8.x-A, ARMv8-R, ARMv8-M;
* - ARM-AA64, ARM-aa64
*
*/
class CoreArchProfileMap
@ -65,36 +66,12 @@ public:
ocsd_arch_profile_t getArchProfile(const std::string &coreName);
private:
ocsd_arch_profile_t getPatternMatchCoreName(const std::string &coreName);
std::map<std::string, ocsd_arch_profile_t> core_profiles;
std::map<std::string, ocsd_arch_profile_t> arch_profiles;
};
inline ocsd_arch_profile_t CoreArchProfileMap::getArchProfile(const std::string &coreName)
{
ocsd_arch_profile_t ap = { ARCH_UNKNOWN, profile_Unknown };
bool bFound = false;
std::map<std::string, ocsd_arch_profile_t>::const_iterator it;
/* match against the core name map. */
it = core_profiles.find(coreName);
if (it != core_profiles.end())
{
ap = it->second;
bFound = true;
}
/* scan architecture profiles on no core name match */
if (!bFound)
{
it = arch_profiles.find(coreName);
if (it != arch_profiles.end())
ap = it->second;
}
return ap;
}
#endif // ARM_TRC_CORE_ARCH_MAP_H_INCLUDED
/* End of File trc_core_arch_map.h */

View File

@ -73,6 +73,9 @@ public:
componentAttachPt<ITraceErrorLog> *getErrLogAttachPt();
/* init decoder implementation object */
ocsd_err_t Init();
/* configuration - set operational mode for incoming stream (has FSYNCS etc) */
ocsd_err_t Configure(uint32_t cfg_flags);
const uint32_t getConfigFlags() const;
@ -85,9 +88,13 @@ public:
ocsd_datapath_resp_t Reset(); /* reset the decode to the start state, drop partial data - propogate to attached components */
ocsd_datapath_resp_t Flush(); /* flush existing data if possible, retain state - propogate to attached components */
/* demux stats */
void SetDemuxStatsBlock(ocsd_demux_stats_t *pStatsBlock);
private:
TraceFmtDcdImpl *m_pDecoder;
int m_instNum;
};
/** @}*/

View File

@ -69,19 +69,22 @@ public:
void setExcepMarker() { excep_data_marker = 1; };
void setExceptionNum(uint32_t excepNum) { exception_number = excepNum; };
void setTraceOnReason(const trace_on_reason_t reason);
void setUnSyncEOTReason(const unsync_info_t reason);
void setTransactionType(const trace_memtrans_t trans) { mem_trans = trans; };
void setAddrRange(const ocsd_vaddr_t st_addr, const ocsd_vaddr_t en_addr, const int num_instr = 1);
void setLastInstrInfo(const bool exec, const ocsd_instr_type last_i_type, const ocsd_instr_subtype last_i_subtype, const uint8_t size);
void setAddrStart(const ocsd_vaddr_t st_addr) { this->st_addr = st_addr; };
void setAddrStart(const ocsd_vaddr_t st_addr) { this->st_addr = st_addr; };
void setLastInstrCond(const int is_cond) { this->last_instr_cond = is_cond; };
void setSWTInfo(const ocsd_swt_info_t swt_info) { sw_trace_info = swt_info; };
void setExtendedDataPtr(const void *data_ptr);
void setITEInfo(const trace_sw_ite_t sw_instrumentation) { sw_ite = sw_instrumentation; };
void setSyncMarker(const trace_marker_payload_t &marker);
// stringize the element
virtual void toString(std::string &str) const;
@ -208,6 +211,11 @@ inline void OcsdTraceElement::setExtendedDataPtr(const void *data_ptr)
ptr_extended_data = data_ptr;
}
inline void OcsdTraceElement::setSyncMarker(const trace_marker_payload_t &marker)
{
sync_marker = marker;
}
// set persistent data between output packets.
inline void OcsdTraceElement::copyPersistentData(const OcsdTraceElement &src)
{

View File

@ -96,6 +96,7 @@ protected:
/* target access */
ocsd_err_t accessMemory(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, uint32_t *num_bytes, uint8_t *p_buffer);
ocsd_err_t invalidateMemAccCache();
/* instruction decode */
ocsd_err_t instrDecode(ocsd_instr_info *instr_info);
@ -180,6 +181,14 @@ inline ocsd_err_t TrcPktDecodeI::accessMemory(const ocsd_vaddr_t address, const
return OCSD_ERR_DCD_INTERFACE_UNUSED;
}
inline ocsd_err_t TrcPktDecodeI::invalidateMemAccCache()
{
if (!m_uses_memaccess)
return OCSD_ERR_DCD_INTERFACE_UNUSED;
m_mem_access.first()->InvalidateMemAccCache(getCoreSightTraceID());
return OCSD_OK;
}
/**********************************************************************/
template <class P, class Pc>
class TrcPktDecodeBase : public TrcPktDecodeI, public IPktDataIn<P>

View File

@ -43,6 +43,7 @@
#include "trc_component.h"
#include "comp_attach_pt_t.h"
#include "opencsd/ocsd_if_version.h"
/** @defgroup ocsd_pkt_proc OpenCSD Library : Packet Processors.
@brief Classes providing Protocol Packet Processing capability.
@ -76,6 +77,8 @@ public:
const uint8_t *pDataBlock,
uint32_t *numBytesProcessed) = 0;
virtual ocsd_err_t getStatsBlock(ocsd_decode_stats_t **pp_stats) = 0;
virtual void resetStats() = 0;
protected:
/* implementation packet processing interface */
@ -155,6 +158,10 @@ public:
//!< Get the configuration for the decoder.
virtual const Pc *getProtocolConfig() const { return m_config; };
/* stats block access - derived class must init stats for the block to be returned. */
virtual ocsd_err_t getStatsBlock(ocsd_decode_stats_t **pp_stats);
virtual void resetStats(); /* reset the counts - operates separately from decoder reset. */
protected:
/* data output functions */
@ -183,6 +190,14 @@ protected:
const bool checkInit(); // return true if init (configured and at least one output sink attached), false otherwise.
/* stats block updates - called by derived protocol specific decoder */
void statsAddTotalCount(const uint64_t count) { m_stats.channel_total += count; };
void statsAddUnsyncCount(const uint64_t count) { m_stats.channel_unsynced += count; };
void statsAddBadSeqCount(const uint32_t count) { m_stats.bad_sequence_errs += count; };
void statsAddBadHdrCount(const uint32_t count) { m_stats.bad_header_errs += count; };
void statsInit() { m_stats_init = true; }; /* mark stats as in use */
private:
/* decode control */
ocsd_datapath_resp_t Reset(const ocsd_trc_index_t index);
@ -195,20 +210,29 @@ private:
componentAttachPt<ITrcPktIndexer<Pt>> m_pkt_indexer_i;
bool m_b_is_init;
/* decode statistics block */
ocsd_decode_stats_t m_stats;
bool m_stats_init; /*< true if the specific decoder is using the stats */
};
template<class P,class Pt, class Pc> TrcPktProcBase<P, Pt, Pc>::TrcPktProcBase(const char *component_name) :
TrcPktProcI(component_name),
m_config(0),
m_b_is_init(false)
m_b_is_init(false),
m_stats_init(false)
{
resetStats();
}
template<class P,class Pt, class Pc> TrcPktProcBase<P, Pt, Pc>::TrcPktProcBase(const char *component_name, int instIDNum) :
TrcPktProcI(component_name, instIDNum),
m_config(0),
m_b_is_init(false)
m_b_is_init(false),
m_stats_init(false)
{
resetStats();
}
template<class P,class Pt, class Pc> TrcPktProcBase<P, Pt, Pc>::~TrcPktProcBase()
@ -405,6 +429,26 @@ template<class P,class Pt, class Pc> const bool TrcPktProcBase<P, Pt, Pc>::check
return m_b_is_init;
}
template<class P,class Pt, class Pc> ocsd_err_t TrcPktProcBase<P, Pt, Pc>::getStatsBlock(ocsd_decode_stats_t **pp_stats)
{
*pp_stats = &m_stats;
return m_stats_init ? OCSD_OK : OCSD_ERR_NOT_INIT;
}
template<class P,class Pt, class Pc> void TrcPktProcBase<P, Pt, Pc>::resetStats()
{
m_stats.version = OCSD_VER_NUM;
m_stats.revision = OCSD_STATS_REVISION;
m_stats.channel_total = 0;
m_stats.channel_unsynced = 0;
m_stats.bad_header_errs = 0;
m_stats.bad_sequence_errs = 0;
m_stats.demux.frame_bytes = 0;
m_stats.demux.no_id_bytes = 0;
m_stats.demux.valid_id_bytes = 0;
}
/** @}*/
#endif // ARM_TRC_PKT_PROC_BASE_H_INCLUDED

View File

@ -44,7 +44,7 @@
/* supplementary decode information */
struct decode_info {
uint16_t arch_version;
ocsd_arch_version_t arch_version;
ocsd_instr_subtype instr_sub_type;
};
@ -121,7 +121,8 @@ arm_barrier_t inst_A64_barrier(uint32_t inst);
int inst_ARM_wfiwfe(uint32_t inst);
int inst_Thumb_wfiwfe(uint32_t inst);
int inst_A64_wfiwfe(uint32_t inst);
int inst_A64_wfiwfe(uint32_t inst, struct decode_info *info);
int inst_A64_Tstart(uint32_t inst);
/*
Test whether an instruction is definitely undefined, e.g. because

View File

@ -47,7 +47,7 @@
*
* This interface provides a monitor point for the packet processor block.
* The templated interface is called with a complete packet of the given
* type, plus the raw packet bytes. Use for tools which need to display compplete
* type, plus the raw packet bytes. Use for tools which need to display complete
* packets or require additional processing on raw packet data.
*
* This interface is not part of the data decode path and cannot provide feedback.

View File

@ -83,6 +83,14 @@ public:
const ocsd_mem_space_acc_t mem_space,
uint32_t *num_bytes,
uint8_t *p_buffer) = 0;
/*!
* Invalidate any caching that the memory accessor functions are using.
* Generally called when a memory context changes in the trace.
*
* @param cs_trace_id : protocol source trace ID.
*/
virtual void InvalidateMemAccCache(const uint8_t cs_trace_id) = 0;
};

View File

@ -61,6 +61,8 @@ public:
uint32_t *num_bytes,
uint8_t *p_buffer);
virtual void InvalidateMemAccCache(const uint8_t cs_trace_id);
// mapper memory area configuration interface
// add an accessor to this map

View File

@ -63,6 +63,7 @@
#include "opencsd/etmv4/etmv4_decoder.h"
#include "opencsd/ptm/ptm_decoder.h"
#include "opencsd/stm/stm_decoder.h"
#include "opencsd/ete/ete_decoder.h"
/** C++ library object types */
#include "common/ocsd_error_logger.h"

View File

@ -46,6 +46,7 @@
#include "opencsd/etmv4/trc_pkt_types_etmv4.h"
#include "opencsd/ptm/trc_pkt_types_ptm.h"
#include "opencsd/stm/trc_pkt_types_stm.h"
#include "opencsd/ete/trc_pkt_types_ete.h"
/** @ingroup lib_c_api
@{*/

View File

@ -210,10 +210,36 @@ OCSD_C_API ocsd_err_t ocsd_dt_attach_packet_callback( const dcd_tree_handle_t h
const void *p_context);
/*!
* Get the stats block for the channel indicated.
* Caller must check p_stats_block->version to esure that the block
* is filled in a compatible manner.
*
* @param handle : Handle to decode tree.
* @param CSID : Configured CoreSight trace ID for the decoder.
* @param p_stats_block: block pointer to set to reference the stats block.
*
* @return ocsd_err_t : Library error code - OCSD_OK if valid block pointer returned,
* OCSD_ERR_NOTINIT if decoder does not support stats counting.
*/
OCSD_C_API ocsd_err_t ocsd_dt_get_decode_stats( const dcd_tree_handle_t handle,
const unsigned char CSID,
ocsd_decode_stats_t **p_stats_block);
/*!
* Reset the stats block for the chosens decode channel.
* stats block is reset independently of the decoder reset to allow counts across
* multiple decode runs.
*
* @param handle : Handle to decode tree.
* @param CSID : Configured CoreSight trace ID for the decoder.
*
* @return ocsd_err_t : Library error code - OCSD_OK if successful.
*/
OCSD_C_API ocsd_err_t ocsd_dt_reset_decode_stats( const dcd_tree_handle_t handle,
const unsigned char CSID);
/** @}*/
/*---------------------- Memory Access for traced opcodes ----------------------------------------------------------------------------------*/
/** @name Library Memory Accessor configuration on decode tree.
@ -373,6 +399,28 @@ OCSD_C_API ocsd_err_t ocsd_def_errlog_set_strprint_cb(const dcd_tree_handle_t ha
*/
OCSD_C_API void ocsd_def_errlog_msgout(const char *msg);
/*!
* Convert an error code into a string.
*
* @param err : error code.
* @param buffer : buffer for return string
* @param buffer_size : length of buffer.
*/
OCSD_C_API void ocsd_err_str(const ocsd_err_t err, char *buffer, const int buffer_size);
/*!
* returns the last error logged by the system, with the related trace byte index, trace channel id,
* and any error message related string.
* If index or channel ID are not valid these will return OCSD_BAD_TRC_INDEX and OCSD_BAD_CS_SRC_ID.
*
* return value is the error code of the last logged error, OCSD_OK for no error available.
*
* @param index : returns trace byte index relating to error, or OCSD_BAD_TRC_INDEX
* @param chan_id : returns trace channel ID relating to error, or OCSD_BAD_CS_SRC_ID
* @param message : buffer to copy the last error message.
* @param message_len: length of message buffer.
*/
OCSD_C_API ocsd_err_t ocsd_get_last_err(ocsd_trc_index_t *index, uint8_t *chan_id, char *message, const int message_len);
/** @}*/

View File

@ -0,0 +1,47 @@
/*
* \file ete_decoder.h
* \brief OpenCSD : Top level header file for ETE decoder.
*
* \copyright Copyright (c) 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_ETE_DECODER_H_INCLUDED
#define ARM_ETE_DECODER_H_INCLUDED
// ETE actually uses extended ETMv4 packet processor and decode
// ETE specifics limited to configuration
//
#include "trc_cmp_cfg_ete.h"
#include "trc_pkt_types_ete.h"
#endif // ARM_ETE_DECODER_H_INCLUDED
/* End of File ete_decoder.h */

View File

@ -0,0 +1,81 @@
/*
* \file trc_cmp_cfg_ete.h
* \brief OpenCSD : ETE configuration
*
* \copyright Copyright (c) 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_CMP_CFG_ETE_H_INCLUDED
#define ARM_TRC_CMP_CFG_ETE_H_INCLUDED
#include "trc_pkt_types_ete.h"
#include "opencsd/etmv4/trc_cmp_cfg_etmv4.h"
/** @addtogroup ocsd_protocol_cfg
@{*/
/** @name ETE configuration
@{*/
/*!
* @class ETEConfig
* @brief Interpreter class for ETE config structure
*
* ETE trace and config are a superset of ETMv4 trace and config - hence
* use the EtmV4Config class as a base.
*/
class ETEConfig : public EtmV4Config
{
public:
ETEConfig();
ETEConfig(const ocsd_ete_cfg *cfg_regs);
~ETEConfig();
//! copy assignment operator for base structure into class.
ETEConfig & operator=(const ocsd_ete_cfg *p_cfg);
//! cast operator returning struct const reference
operator const ocsd_ete_cfg &() const { return m_ete_cfg; };
//! cast operator returning struct const pointer
operator const ocsd_ete_cfg *() const { return &m_ete_cfg; };
private:
void copyV4(); // copy relevent config to underlying structure.
ocsd_ete_cfg m_ete_cfg;
};
/** @}*/
/** @}*/
#endif // ARM_TRC_CMP_CFG_ETE_H_INCLUDED
/* End of File trc_cmp_cfg_ete.h */

View File

@ -0,0 +1,58 @@
/*
* \file trc_dcd_mngr_ete.h
* \brief OpenCSD : ETE decoder creation.
*
* \copyright Copyright (c) 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_DCD_MNGR_ETE_H_INCLUDED
#define ARM_TRC_DCD_MNGR_ETE_H_INCLUDED
#include "common/ocsd_dcd_mngr.h"
#include "trc_cmp_cfg_ete.h"
#include "opencsd/etmv4/trc_pkt_decode_etmv4i.h"
#include "opencsd/etmv4/trc_pkt_proc_etmv4.h"
class DecoderMngrETE : public DecodeMngrFullDcdExCfg< EtmV4ITrcPacket,
ocsd_etmv4_i_pkt_type,
EtmV4Config,
ETEConfig,
ocsd_ete_cfg,
TrcPktProcEtmV4I,
TrcPktDecodeEtmV4I>
{
public:
DecoderMngrETE(const std::string &name) : DecodeMngrFullDcdExCfg(name, OCSD_PROTOCOL_ETE) {};
virtual ~DecoderMngrETE() {};
};
#endif // ARM_TRC_DCD_MNGR_ETE_H_INCLUDED
/* End of File trc_dcd_mngr_ete.h */

View File

@ -0,0 +1,66 @@
/*
* \file trc_pkt_types_ete.h
* \brief OpenCSD : ETE types
*
* \copyright Copyright (c) 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_ETE_H_INCLUDED
#define ARM_TRC_PKT_TYPES_ETE_H_INCLUDED
#include "opencsd/trc_pkt_types.h"
#include "opencsd/etmv4/trc_pkt_types_etmv4.h"
/** @addtogroup trc_pkts
@{*/
/** @name ETE config Types
@{*/
typedef struct _ocsd_ete_cfg
{
uint32_t reg_idr0; /**< ID0 register */
uint32_t reg_idr1; /**< ID1 register */
uint32_t reg_idr2; /**< ID2 register */
uint32_t reg_idr8; /**< ID8 - maxspec */
uint32_t reg_devarch; /**< DevArch register */
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_ete_cfg;
/** @}*/
/** @}*/
#endif // ARM_TRC_PKT_TYPES_ETE_H_INCLUDED
/* End of File trc_pkt_types_ete.h */

View File

@ -81,6 +81,7 @@ public:
const bool hasCycleCountI() const;
const bool hasRetStack() const;
const uint8_t numEvents() const;
const bool eteHasTSMarker() const;
typedef enum _condType {
COND_PASS_FAIL,
@ -104,6 +105,7 @@ public:
const uint32_t TimeStampSize() const;
const bool commitOpt1() const;
const bool commTransP0() const;
/* idr 1 */
const uint8_t MajVersion() const;
@ -151,6 +153,7 @@ public:
const bool enabledCCI() const;
const bool enabledCID() const;
const bool enabledVMID() const;
const bool enabledVMIDOpt() const;
typedef enum {
COND_TR_DIS,
@ -253,6 +256,11 @@ 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;
@ -268,6 +276,11 @@ 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
{
@ -424,6 +437,20 @@ 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)

View File

@ -34,6 +34,7 @@
#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>
@ -56,9 +57,16 @@ typedef enum _p0_elem_t
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_ITE,
} p0_elem_t;
@ -101,6 +109,7 @@ 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;
@ -120,6 +129,14 @@ inline TrcStackElemAddr::TrcStackElemAddr(const ocsd_etmv4_i_pkt_type root_pkt,
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
@ -294,6 +311,55 @@ inline TrcStackElemParam::TrcStackElemParam(const p0_elem_t p0_type, const bool
{
}
/************************************************************/
/** 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)
{
}
/************************************************************/
/* Instrumentation element
*/
class TrcStackElemITE : public TrcStackElem
{
protected:
TrcStackElemITE(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index);
virtual ~TrcStackElemITE() {};
friend class EtmV4P0Stack;
public:
void setITE(const trace_sw_ite_t &ite) { m_ite = ite; };
const trace_sw_ite_t &getITE() { return m_ite; };
private:
trace_sw_ite_t m_ite;
};
inline TrcStackElemITE::TrcStackElemITE(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) :
TrcStackElem(P0_ITE, false, root_pkt, root_index)
{
}
/************************************************************/
/* P0 element stack that allows push of elements, and deletion of elements when done.
*/
@ -329,6 +395,10 @@ public:
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);
TrcStackElemITE *createITEElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const trace_sw_ite_t &ite);
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.

View File

@ -88,11 +88,29 @@ protected:
// 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 an Instrumentation element
ocsd_err_t processITEElem(TrcStackElem *pElem);
// process a bad packet
ocsd_err_t handleBadPacket(const char *reason);
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);
@ -127,6 +145,13 @@ private:
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();
@ -134,6 +159,7 @@ private:
// 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

View File

@ -145,7 +145,7 @@ public:
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);
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);
@ -160,6 +160,7 @@ public:
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);
void setITE(const uint8_t el, const uint64_t value);
// packet status interface - get packet info.
const ocsd_etmv4_i_pkt_type getType() const { return type; };
@ -200,6 +201,10 @@ public:
const int getCommitElem() const { return commit_elements; };
const int getCancelElem() const { return cancel_elements; };
// ITE
const uint8_t getITE_EL() const { return ite_pkt.el; };
const uint64_t getITE_value() const { return ite_pkt.value; };
// packet type
const bool isBadPacket() const;
@ -207,6 +212,8 @@ public:
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;
@ -217,6 +224,8 @@ private:
void push_vaddr();
void pop_vaddr_idx(const uint8_t idx);
const bool isETE() const { return (protocol_version & 0xF0) == 0x50; };
Etmv4PktAddrStack m_addr_stack;
};
@ -412,7 +421,7 @@ inline void EtmV4ITrcPacket::setCondRF4(const uint8_t token)
cond_result.f2f4_token = token;
}
inline void EtmV4ITrcPacket::setContextInfo(const bool update, const uint8_t EL, const uint8_t NS, const uint8_t SF)
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)
@ -421,6 +430,7 @@ inline void EtmV4ITrcPacket::setContextInfo(const bool update, const uint8_t EL,
context.EL = EL;
context.NS = NS;
context.SF = SF;
context.NSE = NSE;
}
}
@ -534,6 +544,12 @@ inline void EtmV4ITrcPacket::pop_vaddr_idx(const uint8_t idx)
m_addr_stack.get_idx(idx, v_addr, v_addr_ISA);
}
inline void EtmV4ITrcPacket::setITE(const uint8_t el, const uint64_t value)
{
ite_pkt.el = el;
ite_pkt.value = value;
}
/** @}*/
#endif // ARM_TRC_PKT_ELEM_ETMV4I_H_INCLUDED

View File

@ -117,6 +117,7 @@ private:
#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
@ -178,9 +179,10 @@ private:
void iPktQ(const uint8_t lastByte);
void iAtom(const uint8_t lastByte);
void iPktInvalidCfg(const uint8_t lastByte); // packet invalid in current config.
void iPktITE(const uint8_t lastByte);
unsigned extractContField(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint32_t &value, const unsigned byte_limit = 5);
unsigned extractContField64(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint64_t &value, const unsigned byte_limit = 9);
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);

View File

@ -1,8 +1,8 @@
/*
* \file trc_pkt_types_etmv4.h
* \brief OpenCSD : ETMv4 packet info
* \brief OpenCSD : ETMv4 / ETE packet info
*
* \copyright Copyright (c) 2015,2019 ARM Limited. All Rights Reserved.
* \copyright Copyright (c) 2015,2019,2022 ARM Limited. All Rights Reserved.
*/
@ -41,7 +41,7 @@
/** @addtogroup trc_pkts
@{*/
/** @name ETMv4 Packet Types
/** @name ETMv4 Packet Types, ETE packet Types
@{*/
/** I stream packets. */
@ -70,9 +70,12 @@ typedef enum _ocsd_etmv4_i_pkt_type
ETM4_PKT_I_FUNC_RET = 0x05, /*!< b00000101 (V8M only) */
// Exceptions
ETM4_PKT_I_EXCEPT = 0x06, /*!< b00000110 */
ETM4_PKT_I_EXCEPT_RTN = 0x07, /*!< b00000111 */
ETM4_PKT_I_EXCEPT_RTN = 0x07, /*!< b00000111 (ETE invalid) */
/* unused encodings 0x08-0xB b00001000 to b00001011 */
/* unused encoding 0x08 b00001000 */
ETE_PKT_I_ITE = 0x09, /*! b00001001 (ETE only) */
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 */
@ -91,7 +94,7 @@ typedef enum _ocsd_etmv4_i_pkt_type
ETM4_PKT_I_CANCEL_F2 = 0x34, /*!< b001101xx */
ETM4_PKT_I_CANCEL_F3 = 0x38, /*!< b00111xxx */
/* conditional instruction tracing */
/* 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 */
@ -116,7 +119,8 @@ typedef enum _ocsd_etmv4_i_pkt_type
ETM4_PKT_I_ADDR_CTXT_L_64IS0 = 0x85, /*!< b10000101 */
ETM4_PKT_I_ADDR_CTXT_L_64IS1, /*!< b10000110 */
/* unused encoding 0x87 b10000111 */
/* unused encodings 0x88-0x8F b10001xxx */
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 */
@ -132,7 +136,15 @@ typedef enum _ocsd_etmv4_i_pkt_type
/* Q packets */
ETM4_PKT_I_Q = 0xA0, /*!< b1010xxxx */
/* unused encodings 0xB0-0xBF b1011xxxx */
/* 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 */
@ -147,15 +159,20 @@ typedef enum _ocsd_etmv4_i_pkt_type
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 enabeld type
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;
@ -167,6 +184,7 @@ typedef struct _etmv4_context_t {
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
@ -256,6 +274,11 @@ typedef struct _ocsd_etmv4_i_pkt
};
} Q_pkt;
struct {
uint8_t el;
uint64_t value;
} ite_pkt;
//! valid bits for packet elements (addresses have their own valid bits).
union {
uint32_t val;
@ -277,6 +300,9 @@ typedef struct _ocsd_etmv4_i_pkt
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;
@ -359,6 +385,9 @@ typedef struct _ocsd_etmv4_cfg
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 */
/** @}*/
/** @}*/

View File

@ -278,11 +278,13 @@ typedef enum _ocsd_arch_version {
ARCH_V7 = 0x0700, /**< V7 architecture */
ARCH_V8 = 0x0800, /**< V8 architecture */
ARCH_V8r3 = 0x0803, /**< V8.3 architecture */
ARCH_AA64 = 0x0864, /**< Min v8r3 plus additional AA64 PE features */
ARCH_V8_max = ARCH_AA64,
} ocsd_arch_version_t;
// macros for arch version comparisons.
#define OCSD_IS_V8_ARCH(arch) ((arch >= ARCH_V8) && (arch <= ARCH_V8r3))
#define OCSD_MIN_V8_ARCH(arch) (arch >= ARCH_V8)
#define OCSD_IS_V8_ARCH(arch) ((arch >= ARCH_V8) && (arch <= ARCH_V8_max))
#define OCSD_IS_ARCH_MINVER(arch, min_arch) (arch >= min_arch)
/** Core Profile */
typedef enum _ocsd_core_profile {
@ -336,8 +338,10 @@ typedef enum _ocsd_isa
*/
typedef enum _ocsd_sec_level
{
ocsd_sec_secure, /**< Core is in secure state */
ocsd_sec_nonsecure /**< Core is in non-secure state */
ocsd_sec_secure, /**< Core is in secure state */
ocsd_sec_nonsecure, /**< Core is in non-secure state */
ocsd_sec_root, /**< PE FEAT_RME: Core is in root state. */
ocsd_sec_realm, /**< PE FEAT_RME: Core is in realm state. */
} ocsd_sec_level ;
/** Exception level type
@ -352,7 +356,7 @@ typedef enum _ocsd_ex_level
} ocsd_ex_level;
/** instruction types - significant for waypoint calculaitons */
/** instruction types - significant for waypoint calculations */
typedef enum _ocsd_instr_type {
OCSD_INSTR_OTHER, /**< Other instruction - not significant for waypoints. */
OCSD_INSTR_BR, /**< Immediate Branch instruction */
@ -360,6 +364,7 @@ typedef enum _ocsd_instr_type {
OCSD_INSTR_ISB, /**< Barrier : ISB instruction */
OCSD_INSTR_DSB_DMB, /**< Barrier : DSB or DMB instruction */
OCSD_INSTR_WFI_WFE, /**< WFI or WFE traced as direct branch */
OCSD_INSTR_TSTART, /**< PE Arch feature FEAT_TME - TSTART instruction */
} ocsd_instr_type;
/** instruction sub types - addiitonal information passed to the output packets
@ -521,10 +526,11 @@ typedef struct _ocsd_file_mem_region {
(common flags share bitfield with pkt processor common flags and create flags)
@{*/
#define OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS 0x00000100 /**< throw error on bad packets input (default is to unsync and wait) */
#define OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS 0x00000100 /**< throw error on bad packets input (default is to warn) */
#define OCSD_OPFLG_PKTDEC_HALT_BAD_PKTS 0x00000200 /**< halt decoder on bad packets (default is to log error and continue by resetting decoder and wait for sync */
/** mask to combine all common packet processor operational control flags */
#define OCSD_OPFLG_PKTDEC_COMMON (OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS)
#define OCSD_OPFLG_PKTDEC_COMMON (OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS | OCSD_OPFLG_PKTDEC_HALT_BAD_PKTS)
/** @}*/
@ -547,6 +553,7 @@ typedef struct _ocsd_file_mem_region {
#define OCSD_BUILTIN_DCD_ETMV4I "ETMV4I" /**< ETMv4 instruction decoder */
#define OCSD_BUILTIN_DCD_ETMV4D "ETMV4D" /**< ETMv4 data decoder */
#define OCSD_BUILTIN_DCD_PTM "PTM" /**< PTM decoder */
#define OCSD_BUILTIN_DCD_ETE "ETE" /**< ETE decoder */
/*! Trace Protocol Builtin Types + extern
*/
@ -559,6 +566,7 @@ typedef enum _ocsd_trace_protocol_t {
OCSD_PROTOCOL_ETMV4D, /**< ETMV4 data trace protocol decoder. */
OCSD_PROTOCOL_PTM, /**< PTM program flow instruction trace protocol decoder. */
OCSD_PROTOCOL_STM, /**< STM system trace protocol decoder. */
OCSD_PROTOCOL_ETE, /**< ETE trace protocol decoder */
/* others to be added here */
OCSD_PROTOCOL_BUILTIN_END, /**< Invalid protocol - built-in protocol types end marker */
@ -627,6 +635,56 @@ typedef struct _ocsd_swt_info {
/** @}*/
/** @name Demux Statistics
Contains statistics for the CoreSight frame demultiplexor.
Counts total bytes sent to decoders registered against a trace ID, bytes in the input stream that are
associated with a trace ID that has no registered decoder, and frame bytes that are not trace data, but
are used to decode the frames - ID bytes, sync bytes etc.
@{*/
typedef struct _ocsd_demux_stats {
uint64_t valid_id_bytes; /**< number of bytes associated with an ID that has a registered decoder */
uint64_t no_id_bytes; /**< number of bytes associated with an ID that has no decoder */
uint64_t reserved_id_bytes; /**< number of bytes associated with reserved IDs */
uint64_t unknown_id_bytes; /**< bytes processed before ID seen in input frames */
uint64_t frame_bytes; /**< number of non-data bytes used for frame de-mux - ID bytes, sync etc */
} ocsd_demux_stats_t;
/** @}*/
/** @name Decode statistics
Contains statistics for bytes decoded by the packet decoder, if statistics are supported.
Stats block instantiated in the base class - derived protocol specific decoder must initialise and
use as required.
The single channel block contains the stats for the requested channel via the API call.
The global demux block contains the totals for all channels and non-data bytes used in CoreSight
frame demux. This block will show identical data for every requested channel via the API.
@{*/
typedef struct _ocsd_decode_stats {
uint32_t version; /**< library version number */
uint16_t revision; /**< revision number - defines the structure version for the stats. */
/* single channel block */
uint64_t channel_total; /**< total bytes processed for this channel */
uint64_t channel_unsynced; /**< number of unsynced bytes processed on this channel */
uint32_t bad_header_errs; /**< number of bad packet header errors */
uint32_t bad_sequence_errs; /**< number of bad packet sequence errors */
ocsd_demux_stats_t demux; /**< global demux stats block */
} ocsd_decode_stats_t;
#define OCSD_STATS_REVISION 0x1
/** @}*/
/** @}*/
#endif // ARM_OCSD_IF_TYPES_H_INCLUDED

View File

@ -42,9 +42,9 @@
/** @name Library Versioning
@{*/
#define OCSD_VER_MAJOR 0x0 /**< Library Major Version */
#define OCSD_VER_MINOR 0xE /**< Library Minor Version */
#define OCSD_VER_PATCH 0x2 /**< Library Patch Version */
#define OCSD_VER_MAJOR 0x1 /**< Library Major Version */
#define OCSD_VER_MINOR 0x4 /**< Library Minor Version */
#define OCSD_VER_PATCH 0x0 /**< Library Patch Version */
/** Library version number - MMMMnnpp format.
MMMM = major version,
@ -53,7 +53,7 @@
*/
#define OCSD_VER_NUM ((OCSD_VER_MAJOR << 16) | (OCSD_VER_MINOR << 8) | OCSD_VER_PATCH)
#define OCSD_VER_STRING "0.14.2" /**< Library Version string */
#define OCSD_VER_STRING "1.4.0" /**< Library Version string */
#define OCSD_LIB_NAME "OpenCSD Library" /**< Library name string */
#define OCSD_LIB_SHORT_NAME "OCSD" /**< Library Short name string */
/** @}*/

View File

@ -239,7 +239,8 @@ inline void TrcPktProcStm::checkSyncNibble()
if((m_nibble == 0) && (m_num_F_nibbles >= 21))
{
m_is_sync = true; //this nibble marks a sync sequence - keep the F nibble count
m_is_sync = true; //this nibble marks a sync sequence
m_num_F_nibbles = 21; // set the F nibble count - lose any extra as unsynced data.
}
else
{

View File

@ -60,7 +60,10 @@ typedef enum _ocsd_gen_trc_elem_t
OCSD_GEN_TRC_ELEM_TIMESTAMP, /*!< Timestamp - preceding elements happeded before this time. */
OCSD_GEN_TRC_ELEM_CYCLE_COUNT, /*!< Cycle count - cycles since last cycle count value - associated with a preceding instruction range. */
OCSD_GEN_TRC_ELEM_EVENT, /*!< Event - trigger or numbered event */
OCSD_GEN_TRC_ELEM_SWTRACE, /*!< Software trace packet - may contain data payload. */
OCSD_GEN_TRC_ELEM_SWTRACE, /*!< Software trace packet - may contain data payload. STM / ITM hardware trace with channel protocol */
OCSD_GEN_TRC_ELEM_SYNC_MARKER, /*!< Synchronisation marker - marks position in stream of an element that is output later. */
OCSD_GEN_TRC_ELEM_MEMTRANS, /*!< Trace indication of transactional memory operations. */
OCSD_GEN_TRC_ELEM_INSTRUMENTATION, /*!< PE instrumentation trace - PE generated SW trace, application dependent protocol. */
OCSD_GEN_TRC_ELEM_CUSTOM, /*!< Fully custom packet type - used by none-ARM architecture decoders */
} ocsd_gen_trc_elem_t;
@ -86,6 +89,27 @@ typedef enum _unsync_info_t {
UNSYNC_EOT, /**< end of trace - no additional info */
} unsync_info_t;
typedef enum _trace_sync_marker_t {
ELEM_MARKER_TS, /**< Marker for timestamp element */
} trace_sync_marker_t;
typedef struct _trace_marker_payload_t {
trace_sync_marker_t type; /**< type of sync marker */
uint32_t value; /**< sync marker value - usage depends on type */
} trace_marker_payload_t;
typedef enum _memtrans_t {
OCSD_MEM_TRANS_TRACE_INIT,/**< Trace started while PE in transactional state */
OCSD_MEM_TRANS_START, /**< Trace after this packet is part of a transactional memory sequence */
OCSD_MEM_TRANS_COMMIT, /**< Transactional memory sequence valid. */
OCSD_MEM_TRANS_FAIL, /**< Transactional memory sequence failed - operations since start of transaction have been unwound. */
} trace_memtrans_t;
typedef struct _sw_ite_t {
uint8_t el; /**< exception level for PE sw instrumentation instruction */
uint64_t value; /**< payload for PE sw instrumentation instruction */
} trace_sw_ite_t;
typedef struct _ocsd_generic_trace_elem {
ocsd_gen_trc_elem_t elem_type; /**< Element type - remaining data interpreted according to this value */
ocsd_isa isa; /**< instruction set for executed instructions */
@ -122,6 +146,9 @@ typedef struct _ocsd_generic_trace_elem {
ocsd_swt_info_t sw_trace_info; /**< software trace packet info */
uint32_t num_instr_range; /**< number of instructions covered by range packet (for T32 this cannot be calculated from en-st/i_size) */
unsync_info_t unsync_eot_info; /**< additional information for unsync / end-of-trace packets. */
trace_marker_payload_t sync_marker; /**< marker element - sync later element to position in stream */
trace_memtrans_t mem_trans; /**< memory transaction packet - transaction event */
trace_sw_ite_t sw_ite; /**< PE sw instrumentation using FEAT_ITE */
};
const void *ptr_extended_data; /**< pointer to extended data buffer (data trace, sw trace payload) / custom structure */

View File

@ -234,8 +234,24 @@ OCSD_C_API ocsd_err_t ocsd_dt_attach_packet_callback( const dcd_tree_handle_t h
return err;
}
/*** Decode tree set element output */
OCSD_C_API ocsd_err_t ocsd_dt_get_decode_stats(const dcd_tree_handle_t handle,
const unsigned char CSID,
ocsd_decode_stats_t **p_stats_block)
{
DecodeTree *pDT = static_cast<DecodeTree *>(handle);
return pDT->getDecoderStats(CSID, p_stats_block);
}
OCSD_C_API ocsd_err_t ocsd_dt_reset_decode_stats(const dcd_tree_handle_t handle,
const unsigned char CSID)
{
DecodeTree *pDT = static_cast<DecodeTree *>(handle);
return pDT->resetDecoderStats(CSID);
}
/*** Decode tree set element output */
OCSD_C_API ocsd_err_t ocsd_dt_set_gen_elem_outfn(const dcd_tree_handle_t handle, FnTraceElemIn pFn, const void *p_context)
{
@ -470,6 +486,39 @@ OCSD_C_API ocsd_err_t ocsd_dt_set_pkt_protocol_printer(const dcd_tree_handle_t h
return err;
}
OCSD_C_API void ocsd_err_str(const ocsd_err_t err, char *buffer, const int buffer_size)
{
std::string err_str;
err_str = ocsdError::getErrorString(ocsdError(OCSD_ERR_SEV_ERROR, err));
strncpy(buffer, err_str.c_str(), buffer_size - 1);
buffer[buffer_size - 1] = 0;
}
OCSD_C_API ocsd_err_t ocsd_get_last_err(ocsd_trc_index_t *index, uint8_t *chan_id, char *message, const int message_len)
{
ocsdError *p_err;
ocsd_err_t err = OCSD_OK;
std::string err_str;
p_err = DecodeTree::getDefaultErrorLogger()->GetLastError();
if (p_err)
{
*index = p_err->getErrorIndex();
*chan_id = p_err->getErrorChanID();
err_str = p_err->getErrorString(ocsdError(p_err));
strncpy(message, err_str.c_str(), message_len - 1);
message[message_len - 1] = 0;
err = p_err->getErrorCode();
}
else
{
message[0] = 0;
*index = OCSD_BAD_TRC_INDEX;
*chan_id = OCSD_BAD_CS_SRC_ID;
}
return err;
}
/*******************************************************************************/
/* C API local fns */
/*******************************************************************************/

View File

@ -0,0 +1,98 @@
/*
* \file trc_cmp_cfg_ete.cpp
* \brief OpenCSD : ETE config class
*
* \copyright Copyright (c) 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.
*/
#include "opencsd/ete/trc_cmp_cfg_ete.h"
ETEConfig::ETEConfig() : EtmV4Config()
{
m_ete_cfg.reg_idr0 = 0x28000EA1;
m_ete_cfg.reg_idr1 = 0x4100FFF3;
m_ete_cfg.reg_idr2 = 0x00000488;
m_ete_cfg.reg_idr8 = 0;
m_ete_cfg.reg_configr = 0xC1;
m_ete_cfg.reg_traceidr = 0;
m_ete_cfg.arch_ver = ARCH_AA64;
m_ete_cfg.core_prof = profile_CortexA;
m_ete_cfg.reg_devarch = 0x47705A13;
copyV4();
}
ETEConfig::ETEConfig(const ocsd_ete_cfg *cfg_regs) : EtmV4Config()
{
m_ete_cfg = *cfg_regs;
copyV4();
}
ETEConfig::~ETEConfig()
{
}
//! copy assignment operator for base structure into class.
ETEConfig & ETEConfig::operator=(const ocsd_ete_cfg *p_cfg)
{
m_ete_cfg = *p_cfg;
copyV4();
return *this;
}
//! cast operator returning struct const reference
//operator const ocsd_ete_cfg &() const { return m_ete_cfg; };
//! cast operator returning struct const pointer
//operator const ocsd_ete_cfg *() const { return &m_ete_cfg; };
// ete superset of etmv4 - move info to underlying structure.
void ETEConfig::copyV4()
{
// copy over 1:1 regs
m_cfg.reg_idr0 = m_ete_cfg.reg_idr0;
m_cfg.reg_idr1 = m_ete_cfg.reg_idr1;
m_cfg.reg_idr2 = m_ete_cfg.reg_idr2;
m_cfg.reg_idr8 = m_ete_cfg.reg_idr8;
m_cfg.reg_idr9 = 0;
m_cfg.reg_idr10 = 0;
m_cfg.reg_idr11 = 0;
m_cfg.reg_idr12 = 0;
m_cfg.reg_idr13 = 0;
m_cfg.reg_configr = m_ete_cfg.reg_configr;
m_cfg.reg_traceidr = m_ete_cfg.reg_traceidr;
m_cfg.core_prof = m_ete_cfg.core_prof;
m_cfg.arch_ver = m_ete_cfg.arch_ver;
// override major / minor version as part of devarch
m_MajVer = (uint8_t)((m_ete_cfg.reg_devarch & 0xF000) >> 12);
m_MinVer = (uint8_t)((m_ete_cfg.reg_devarch & 0xF0000) >> 16);
}
/* End of File trc_cmp_cfg_ete.cpp */

View File

@ -659,7 +659,7 @@ void EtmV3TrcPacket::getExcepStr(std::string &excepStr) const
"IRQ4", "IRQ5", "IRQ6", "IRQ7",
"IRQ0","usage Fault","NMI","SVC",
"DebugMonitor", "Mem Manage","PendSV","SysTick",
"Reserved","PE Reset","Reserved","HardFault"
"Reserved","PE Reset","Reserved","HardFault",
"Reserved","BusFault","Reserved","Reserved"
};

View File

@ -98,7 +98,7 @@ void EtmV4Config::CalcVMIDSize()
uint32_t vmidszF = (m_cfg.reg_idr2 >> 10) & 0x1F;
if(vmidszF == 1)
m_VMIDSize = 8;
else if(MinVersion() > 0)
else if(FullVersion() > 0x40)
{
if(vmidszF == 2)
m_VMIDSize = 16;

View File

@ -128,6 +128,40 @@ TrcStackQElem *EtmV4P0Stack::createQElem(const ocsd_etmv4_i_pkt_type root_pkt, c
return pElem;
}
TrcStackElemMarker *EtmV4P0Stack::createMarkerElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const trace_marker_payload_t &marker)
{
TrcStackElemMarker *pElem = new (std::nothrow) TrcStackElemMarker(root_pkt, root_index);
if (pElem)
{
pElem->setMarker(marker);
push_front(pElem);
}
return pElem;
}
TrcStackElemAddr *EtmV4P0Stack::createSrcAddrElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const etmv4_addr_val_t &addr_val)
{
TrcStackElemAddr *pElem = new (std::nothrow) TrcStackElemAddr(root_pkt, root_index, true);
if (pElem)
{
pElem->setAddr(addr_val);
push_front(pElem);
}
return pElem;
}
TrcStackElemITE *EtmV4P0Stack::createITEElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const trace_sw_ite_t &ite)
{
TrcStackElemITE *pElem = new (std::nothrow) TrcStackElemITE(root_pkt, root_index);
if (pElem)
{
pElem->setITE(ite);
push_front(pElem);
}
return pElem;
}
// iteration functions
void EtmV4P0Stack::from_front_init()
{
@ -150,6 +184,10 @@ void EtmV4P0Stack::erase_curr_from_front()
erase_iter = m_iter;
erase_iter--;
m_P0_stack.erase(erase_iter);
// explicitly delete the item here as the caller can no longer reference it.
// fixes memory leak from github issue #52
delete *erase_iter;
}

View File

@ -38,6 +38,7 @@
EtmV4ITrcPacket::EtmV4ITrcPacket()
{
protocol_version = 0x42; // min protocol version.
}
EtmV4ITrcPacket::~EtmV4ITrcPacket()
@ -101,6 +102,8 @@ void EtmV4ITrcPacket::toString(std::string &str) const
contextStr(ctxtStr);
case ETM4_PKT_I_ADDR_L_32IS0:
case ETM4_PKT_I_ADDR_L_32IS1:
case ETE_PKT_I_SRC_ADDR_L_32IS0:
case ETE_PKT_I_SRC_ADDR_L_32IS1:
trcPrintableElem::getValStr(valStr, (v_addr.size == VA_64BIT) ? 64 : 32, v_addr.valid_bits, v_addr.val, true, (v_addr.pkt_bits < 32) ? v_addr.pkt_bits : 0);
str += "; Addr=" + valStr + "; " + ctxtStr;
break;
@ -110,6 +113,8 @@ void EtmV4ITrcPacket::toString(std::string &str) const
contextStr(ctxtStr);
case ETM4_PKT_I_ADDR_L_64IS0:
case ETM4_PKT_I_ADDR_L_64IS1:
case ETE_PKT_I_SRC_ADDR_L_64IS0:
case ETE_PKT_I_SRC_ADDR_L_64IS1:
trcPrintableElem::getValStr(valStr, (v_addr.size == VA_64BIT) ? 64 : 32, v_addr.valid_bits, v_addr.val, true, (v_addr.pkt_bits < 64) ? v_addr.pkt_bits : 0);
str += "; Addr=" + valStr + "; " + ctxtStr;
break;
@ -121,11 +126,14 @@ void EtmV4ITrcPacket::toString(std::string &str) const
case ETM4_PKT_I_ADDR_S_IS0:
case ETM4_PKT_I_ADDR_S_IS1:
case ETE_PKT_I_SRC_ADDR_S_IS0:
case ETE_PKT_I_SRC_ADDR_S_IS1:
trcPrintableElem::getValStr(valStr, (v_addr.size == VA_64BIT) ? 64 : 32, v_addr.valid_bits, v_addr.val, true, v_addr.pkt_bits);
str += "; Addr=" + valStr;
break;
case ETM4_PKT_I_ADDR_MATCH:
case ETE_PKT_I_SRC_ADDR_MATCH:
addrMatchIdx(valStr);
str += ", " + valStr;
trcPrintableElem::getValStr(valStr, (v_addr.size == VA_64BIT) ? 64 : 32, v_addr.valid_bits, v_addr.val, true);
@ -161,7 +169,10 @@ void EtmV4ITrcPacket::toString(std::string &str) const
{
std::ostringstream oss;
oss << "; INFO=" << std::hex << "0x" << trace_info.val;
oss << " { CC." << std::dec << trace_info.bits.cc_enabled << " }";
oss << " { CC." << std::dec << trace_info.bits.cc_enabled;
if (isETE())
oss << ", TSTATE." << std::dec << trace_info.bits.in_trans_state;
oss << " }";
if (trace_info.bits.cc_enabled)
oss << "; CC_THRESHOLD=" << std::hex << "0x" << cc_threshold;
str += oss.str();
@ -264,6 +275,14 @@ void EtmV4ITrcPacket::toString(std::string &str) const
}
}
break;
case ETE_PKT_I_ITE:
{
std::ostringstream oss;
oss << "; EL" << std::dec << (int)ite_pkt.el << "; Payload=0x" << std::hex << ite_pkt.value;
str += oss.str();
}
break;
}
}
@ -349,6 +368,16 @@ const char *EtmV4ITrcPacket::packetTypeName(const ocsd_etmv4_i_pkt_type type, co
pName = "I_EXCEPT_RTN";
pDesc = "Exception Return.";
break;
case ETE_PKT_I_TRANS_ST:
pName = "I_TRANS_ST";
pDesc = "Transaction Start.";
break;
case ETE_PKT_I_TRANS_COMMIT:
pName = "I_TRANS_COMMIT";
pDesc = "Transaction Commit.";
break;
case ETM4_PKT_I_CCNT_F1:
pName = "I_CCNT_F1";
@ -481,6 +510,11 @@ const char *EtmV4ITrcPacket::packetTypeName(const ocsd_etmv4_i_pkt_type type, co
pDesc = "Address & Context, Long, 64 bit, IS1.";
break;
case ETE_PKT_I_TS_MARKER:
pName = "I_TS_MARKER";
pDesc = "Timestamp Marker";
break;
case ETM4_PKT_I_ADDR_MATCH:
pName = "I_ADDR_MATCH";
pDesc = "Exact Address Match.";
@ -521,6 +555,41 @@ const char *EtmV4ITrcPacket::packetTypeName(const ocsd_etmv4_i_pkt_type type, co
pDesc = "Q Packet.";
break;
case ETE_PKT_I_SRC_ADDR_MATCH:
pName = "I_SRC_ADDR_MATCH";
pDesc = "Exact Source Address Match.";
break;
case ETE_PKT_I_SRC_ADDR_S_IS0:
pName = "I_SRC_ADDR_S_IS0";
pDesc = "Source Address, Short, IS0.";
break;
case ETE_PKT_I_SRC_ADDR_S_IS1:
pName = "I_SRC_ADDR_S_IS1";
pDesc = "Source Address, Short, IS1.";
break;
case ETE_PKT_I_SRC_ADDR_L_32IS0:
pName = "I_SCR_ADDR_L_32IS0";
pDesc = "Source Address, Long, 32 bit, IS0.";
break;
case ETE_PKT_I_SRC_ADDR_L_32IS1:
pName = "I_SRC_ADDR_L_32IS1";
pDesc = "Source Address, Long, 32 bit, IS1.";
break;
case ETE_PKT_I_SRC_ADDR_L_64IS0:
pName = "I_SRC_ADDR_L_64IS0";
pDesc = "Source Address, Long, 64 bit, IS0.";
break;
case ETE_PKT_I_SRC_ADDR_L_64IS1:
pName = "I_SRC_ADDR_L_64IS1";
pDesc = "Source Address, Long, 64 bit, IS1.";
break;
case ETM4_PKT_I_ATOM_F6:
pName = "I_ATOM_F6";
pDesc = "Atom format 6.";
@ -566,6 +635,21 @@ const char *EtmV4ITrcPacket::packetTypeName(const ocsd_etmv4_i_pkt_type type, co
pDesc = "Overflow.";
break;
case ETE_PKT_I_PE_RESET:
pName = "I_PE_RESET";
pDesc = "PE Reset.";
break;
case ETE_PKT_I_TRANS_FAIL:
pName = "I_TRANS_FAIL";
pDesc = "Transaction Fail.";
break;
case ETE_PKT_I_ITE:
pName = "I_ITE";
pDesc = "Instrumentation";
break;
default:
break;
}

View File

@ -45,6 +45,9 @@
static const uint32_t ETMV4_SUPPORTED_OP_FLAGS = OCSD_OPFLG_PKTPROC_COMMON;
// test defines - if testing with ETMv4 sources, disable error on ERET.
// #define ETE_TRACE_ERET_AS_IGNORE
/* trace etmv4 packet processing class */
TrcPktProcEtmV4I::TrcPktProcEtmV4I() : TrcPktProcBase(ETMV4I_PKTS_NAME),
m_isInit(false),
@ -70,7 +73,9 @@ ocsd_err_t TrcPktProcEtmV4I::onProtocolConfig()
InitProcessorState();
m_config = *TrcPktProcBase::getProtocolConfig();
BuildIPacketTable(); // packet table based on config
m_curr_packet.setProtocolVersion(m_config.FullVersion());
m_isInit = true;
statsInit();
return OCSD_OK;
}
@ -152,6 +157,10 @@ ocsd_datapath_resp_t TrcPktProcEtmV4I::processData( const ocsd_trc_index_t inde
(err.getErrorCode() == OCSD_ERR_INVALID_PCKT_HDR))
{
// send invalid packets up the pipe to let the next stage decide what to do.
if (err.getErrorCode() == OCSD_ERR_INVALID_PCKT_HDR)
statsAddBadHdrCount(1);
else
statsAddBadSeqCount(1);
m_process_state = SEND_PKT;
done = false;
}
@ -171,6 +180,7 @@ ocsd_datapath_resp_t TrcPktProcEtmV4I::processData( const ocsd_trc_index_t inde
}
} while (!done);
statsAddTotalCount(m_trcIn.processed());
*numBytesProcessed = m_trcIn.processed();
return resp;
}
@ -241,8 +251,8 @@ ocsd_datapath_resp_t TrcPktProcEtmV4I::outputUnsyncedRawPacket()
{
ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
outputRawPacketToMonitor(m_packet_index,&m_curr_packet,m_dump_unsynced_bytes,&m_currPacketData[0]);
statsAddUnsyncCount(m_dump_unsynced_bytes);
outputRawPacketToMonitor(m_packet_index,&m_curr_packet,m_dump_unsynced_bytes,&m_currPacketData[0]);
if(!m_sent_notsync_packet)
{
@ -290,6 +300,7 @@ void TrcPktProcEtmV4I::iPktNoPayload(const uint8_t lastByte)
switch(m_curr_packet.type)
{
case ETM4_PKT_I_ADDR_MATCH:
case ETE_PKT_I_SRC_ADDR_MATCH:
m_curr_packet.setAddressExactMatch(lastByte & 0x3);
break;
@ -307,6 +318,8 @@ void TrcPktProcEtmV4I::iPktNoPayload(const uint8_t lastByte)
case ETM4_PKT_I_EXCEPT_RTN:
case ETM4_PKT_I_TRACE_ON:
case ETM4_PKT_I_FUNC_RET:
case ETE_PKT_I_TRANS_ST:
case ETE_PKT_I_TRANS_COMMIT:
case ETM4_PKT_I_IGNORE:
default: break;
}
@ -437,6 +450,8 @@ void TrcPktProcEtmV4I::iPktTraceInfo(const uint8_t lastByte)
m_tinfo_sections.sectFlags |= (lastByte & 0x80) ? 0 : TINFO_SPEC_SECT;
else if(!(m_tinfo_sections.sectFlags & TINFO_CYCT_SECT))
m_tinfo_sections.sectFlags |= (lastByte & 0x80) ? 0 : TINFO_CYCT_SECT;
else if (!(m_tinfo_sections.sectFlags & TINFO_WNDW_SECT))
m_tinfo_sections.sectFlags |= (lastByte & 0x80) ? 0 : TINFO_WNDW_SECT;
}
// all sections accounted for?
@ -469,6 +484,11 @@ void TrcPktProcEtmV4I::iPktTraceInfo(const uint8_t lastByte)
idx += extractContField(m_currPacketData,idx,fieldVal);
m_curr_packet.setTraceInfoCyct(fieldVal);
}
if ((presSect & TINFO_WNDW_SECT) && (idx < m_currPacketData.size()))
{
idx += extractContField(m_currPacketData, idx, fieldVal);
/* Trace commit window unsupported in current ETE versions */
}
m_process_state = SEND_PKT;
m_first_trace_info = true;
}
@ -502,8 +522,11 @@ void TrcPktProcEtmV4I::iPktTimestamp(const uint8_t lastByte)
{
int idx = 1;
uint64_t tsVal;
int ts_bytes = extractContField64(m_currPacketData, idx, tsVal);
int ts_bits = ts_bytes < 7 ? ts_bytes * 7 : 64;
int ts_bytes = extractTSField64(m_currPacketData, idx, tsVal);
int ts_bits;
// if ts_bytes 8 or less, then cont bits on each byte, otherwise full 64 bit value for 9 bytes
ts_bits = ts_bytes < 9 ? ts_bytes * 7 : 64;
if(!m_curr_packet.pkt_valid.bits.ts_valid && m_first_trace_info)
ts_bits = 64; // after trace info, missing bits are all 0.
@ -534,6 +557,13 @@ void TrcPktProcEtmV4I::iPktException(const uint8_t lastByte)
case 1: m_excep_size = 3; break;
case 2: if((lastByte & 0x80) == 0x00)
m_excep_size = 2;
// ETE exception reset or trans failed
if (m_config.MajVersion() >= 0x5)
{
excep_type = (m_currPacketData[1] >> 1) & 0x1F;
if ((excep_type == 0x0) || (excep_type == 0x18))
m_excep_size = 3;
}
break;
}
@ -553,6 +583,18 @@ void TrcPktProcEtmV4I::iPktException(const uint8_t lastByte)
m_curr_packet.setExceptionInfo(excep_type,addr_interp,m_fault_pending, m_type);
m_process_state = SEND_PKT;
// ETE exception reset or trans failed
if (m_config.MajVersion() >= 0x5)
{
if ((excep_type == 0x0) || (excep_type == 0x18))
{
m_curr_packet.set64BitAddress(0, 0);
if (excep_type == 0x18)
m_curr_packet.setType(ETE_PKT_I_TRANS_FAIL);
else
m_curr_packet.setType(ETE_PKT_I_PE_RESET);
}
}
// allow the standard address packet handlers to process the address packet field for the exception.
}
}
@ -833,7 +875,7 @@ void TrcPktProcEtmV4I::extractAndSetContextInfo(const std::vector<uint8_t> &buff
// on input, buffer index points at the info byte - always present
uint8_t infoByte = m_currPacketData[st_idx];
m_curr_packet.setContextInfo(true, (infoByte & 0x3), (infoByte >> 5) & 0x1, (infoByte >> 4) & 0x1);
m_curr_packet.setContextInfo(true, (infoByte & 0x3), (infoByte >> 5) & 0x1, (infoByte >> 4) & 0x1, (infoByte >> 3) & 0x1);
// see if there are VMID and CID bytes, and how many.
int nVMID_bytes = ((infoByte & 0x40) == 0x40) ? (m_config.vmidSize()/8) : 0;
@ -937,7 +979,8 @@ void TrcPktProcEtmV4I::iPktShortAddr(const uint8_t lastByte)
{
m_addr_done = false;
m_addrIS = 0;
if (lastByte == ETM4_PKT_I_ADDR_S_IS1)
if ((lastByte == ETM4_PKT_I_ADDR_S_IS1) ||
(lastByte == ETE_PKT_I_SRC_ADDR_S_IS1))
m_addrIS = 1;
}
else if(!m_addr_done)
@ -988,14 +1031,18 @@ void TrcPktProcEtmV4I::iPktLongAddr(const uint8_t lastByte)
switch(m_curr_packet.type)
{
case ETM4_PKT_I_ADDR_L_32IS1:
case ETE_PKT_I_SRC_ADDR_L_32IS1:
m_addrIS = 1;
case ETM4_PKT_I_ADDR_L_32IS0:
case ETE_PKT_I_SRC_ADDR_L_32IS0:
m_addrBytes = 4;
break;
case ETM4_PKT_I_ADDR_L_64IS1:
case ETE_PKT_I_SRC_ADDR_L_64IS1:
m_addrIS = 1;
case ETM4_PKT_I_ADDR_L_64IS0:
case ETE_PKT_I_SRC_ADDR_L_64IS0:
m_addrBytes = 8;
m_bAddr64bit = true;
break;
@ -1203,6 +1250,23 @@ void TrcPktProcEtmV4I::iAtom(const uint8_t lastByte)
m_process_state = SEND_PKT;
}
void TrcPktProcEtmV4I::iPktITE(const uint8_t /* lastByte */)
{
uint64_t value;
int shift = 0;
/* packet is always 10 bytes, Header, EL info byte, 8 bytes payload */
if (m_currPacketData.size() == 10) {
value = 0;
for (int i = 2; i < 10; i++) {
value |= ((uint64_t)m_currPacketData[i]) << shift;
shift += 8;
}
m_curr_packet.setITE(m_currPacketData[1], value);
m_process_state = SEND_PKT;
}
}
// header byte processing is table driven.
void TrcPktProcEtmV4I::BuildIPacketTable()
{
@ -1247,7 +1311,35 @@ void TrcPktProcEtmV4I::BuildIPacketTable()
// b0000 0111 - exception return
m_i_table[0x07].pkt_type = ETM4_PKT_I_EXCEPT_RTN;
m_i_table[0x07].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;
if (m_config.MajVersion() >= 0x5) // not valid for ETE
{
#ifdef ETE_TRACE_ERET_AS_IGNORE
m_i_table[0x07].pkt_type = ETM4_PKT_I_IGNORE;
m_i_table[0x07].pptkFn = &EtmV4IPktProcImpl::iPktNoPayload;
#else
m_i_table[0x07].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
#endif
}
else
m_i_table[0x07].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;
// b00001010, b00001011 ETE TRANS packets
// b00001001 - ETE sw instrumentation packet
if (m_config.MajVersion() >= 0x5)
{
m_i_table[0x0A].pkt_type = ETE_PKT_I_TRANS_ST;
m_i_table[0x0A].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;
m_i_table[0x0B].pkt_type = ETE_PKT_I_TRANS_COMMIT;
m_i_table[0x0B].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;
// FEAT_ITE - sw instrumentation packet
if (m_config.MinVersion() >= 0x3)
{
m_i_table[0x09].pkt_type = ETE_PKT_I_ITE;
m_i_table[0x09].pptkFn = &TrcPktProcEtmV4I::iPktITE;
}
}
// b0000 110x - cycle count f2
// b0000 111x - cycle count f1
@ -1443,6 +1535,12 @@ void TrcPktProcEtmV4I::BuildIPacketTable()
m_i_table[0x85+i].pptkFn = &TrcPktProcEtmV4I::iPktAddrCtxt;
}
// 0b1000 1000 - ETE 1.1 TS Marker. also ETMv4.6
if(m_config.FullVersion() >= 0x46)
{
m_i_table[0x88].pkt_type = ETE_PKT_I_TS_MARKER;
m_i_table[0x88].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;
}
// 0b1001 0000 to b1001 0010 - exact match addr
for(int i = 0; i < 3; i++)
{
@ -1492,6 +1590,30 @@ void TrcPktProcEtmV4I::BuildIPacketTable()
}
}
// b10110000 - b10111001 - ETE src address packets
if (m_config.FullVersion() >= 0x50)
{
for (int i = 0; i < 3; i++)
{
m_i_table[0xB0 + i].pkt_type = ETE_PKT_I_SRC_ADDR_MATCH;
m_i_table[0xB0 + i].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;
}
m_i_table[0xB4].pkt_type = ETE_PKT_I_SRC_ADDR_S_IS0;
m_i_table[0xB4].pptkFn = &TrcPktProcEtmV4I::iPktShortAddr;
m_i_table[0xB5].pkt_type = ETE_PKT_I_SRC_ADDR_S_IS1;
m_i_table[0xB5].pptkFn = &TrcPktProcEtmV4I::iPktShortAddr;
m_i_table[0xB6].pkt_type = ETE_PKT_I_SRC_ADDR_L_32IS0;
m_i_table[0xB6].pptkFn = &TrcPktProcEtmV4I::iPktLongAddr;
m_i_table[0xB7].pkt_type = ETE_PKT_I_SRC_ADDR_L_32IS1;
m_i_table[0xB7].pptkFn = &TrcPktProcEtmV4I::iPktLongAddr;
m_i_table[0xB8].pkt_type = ETE_PKT_I_SRC_ADDR_L_64IS0;
m_i_table[0xB8].pptkFn = &TrcPktProcEtmV4I::iPktLongAddr;
m_i_table[0xB9].pkt_type = ETE_PKT_I_SRC_ADDR_L_64IS1;
m_i_table[0xB9].pptkFn = &TrcPktProcEtmV4I::iPktLongAddr;
}
// Atom Packets - all no payload but have specific pattern generation fn
for(int i = 0xC0; i <= 0xD4; i++) // atom f6
{
@ -1559,20 +1681,33 @@ void TrcPktProcEtmV4I::BuildIPacketTable()
return idx;
}
unsigned TrcPktProcEtmV4I::extractContField64(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint64_t &value, const unsigned byte_limit /*= 9*/)
unsigned TrcPktProcEtmV4I::extractTSField64(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint64_t &value)
{
const unsigned max_byte_idx = 8; /* the 9th byte, index 8, will use full 8 bits for value */
unsigned idx = 0;
bool lastByte = false;
uint8_t byteVal;
uint8_t byteValMask = 0x7f;
/* init value */
value = 0;
while(!lastByte && (idx < byte_limit)) // max 9 bytes for 64 bit value;
while(!lastByte) // max 9 bytes for 64 bit value;
{
if(buffer.size() > (st_idx + idx))
{
// each byte has seven bits + cont bit
byteVal = buffer[(st_idx + idx)];
lastByte = (byteVal & 0x80) != 0x80;
value |= ((uint64_t)(byteVal & 0x7F)) << (idx * 7);
/* detect the final byte - which uses full 8 bits as value */
if (idx == max_byte_idx)
{
byteValMask = 0xFF; /* last byte of 9, no cont bit */
lastByte = true;
}
else
lastByte = (byteVal & 0x80) != 0x80;
value |= ((uint64_t)(byteVal & byteValMask)) << (idx * 7);
idx++;
}
else
@ -1580,6 +1715,7 @@ unsigned TrcPktProcEtmV4I::extractContField64(const std::vector<uint8_t> &buffer
throwBadSequenceError("Invalid 64 bit continuation fields in packet");
}
}
// index is the count of bytes used here.
return idx;
}

View File

@ -42,7 +42,7 @@ ocsd_err_t TrcIDecode::DecodeInstruction(ocsd_instr_info *instr_info)
struct decode_info info;
info.instr_sub_type = OCSD_S_INSTR_NONE;
info.arch_version = (uint16_t)(instr_info->pe_type.arch);
info.arch_version = instr_info->pe_type.arch;
switch(instr_info->isa)
{
@ -136,14 +136,12 @@ ocsd_err_t TrcIDecode::DecodeA64(ocsd_instr_info *instr_info, struct decode_info
if(inst_A64_is_indirect_branch_link(instr_info->opcode, &instr_info->is_link, info))
{
instr_info->type = OCSD_INSTR_BR_INDIRECT;
// instr_info->is_link = inst_A64_is_branch_and_link(instr_info->opcode);
}
else if(inst_A64_is_direct_branch_link(instr_info->opcode, &instr_info->is_link, info))
{
inst_A64_branch_destination(instr_info->instr_addr,instr_info->opcode,&branchAddr);
instr_info->type = OCSD_INSTR_BR;
instr_info->branch_addr = (ocsd_vaddr_t)branchAddr;
// instr_info->is_link = inst_A64_is_branch_and_link(instr_info->opcode);
}
else if((barrier = inst_A64_barrier(instr_info->opcode)) != ARM_BARRIER_NONE)
{
@ -160,12 +158,15 @@ ocsd_err_t TrcIDecode::DecodeA64(ocsd_instr_info *instr_info, struct decode_info
break;
}
}
else if (instr_info->wfi_wfe_branch)
else if (instr_info->wfi_wfe_branch &&
inst_A64_wfiwfe(instr_info->opcode, info))
{
if (inst_A64_wfiwfe(instr_info->opcode))
{
instr_info->type = OCSD_INSTR_WFI_WFE;
}
instr_info->type = OCSD_INSTR_WFI_WFE;
}
else if (OCSD_IS_ARCH_MINVER(info->arch_version, ARCH_AA64))
{
if (inst_A64_Tstart(instr_info->opcode))
instr_info->type = OCSD_INSTR_TSTART;
}
instr_info->is_conditional = inst_A64_is_conditional(instr_info->opcode);

View File

@ -244,8 +244,9 @@ int inst_A64_is_direct_branch_link(uint32_t inst, uint8_t *is_link, struct decod
int is_direct_branch = 1;
if ((inst & 0x7c000000) == 0x34000000) {
/* CB, TB */
} else if ((inst & 0xff000010) == 0x54000000) {
} else if ((inst & 0xff000000) == 0x54000000) {
/* B<cond> */
/* BC<cond> 8.8 / 9.3 arch - bit 4 = 1'b1 */
} else if ((inst & 0x7c000000) == 0x14000000) {
/* B, BL imm */
if (inst & 0x80000000) {
@ -258,11 +259,26 @@ int inst_A64_is_direct_branch_link(uint32_t inst, uint8_t *is_link, struct decod
return is_direct_branch;
}
int inst_A64_wfiwfe(uint32_t inst)
int inst_A64_wfiwfe(uint32_t inst, struct decode_info *info)
{
/* WFI, WFE may be traced as branches in etm 4.3++ */
if ((inst & 0xffffffdf) == 0xd503205f)
return 1;
/* new feature introduced post v8.3 */
if (OCSD_IS_ARCH_MINVER(info->arch_version, ARCH_AA64))
{
/* WFIT / WFET for later archs */
if ((inst & 0xffffffc0) == 0xd5031000)
return 1;
}
return 0;
}
int inst_A64_Tstart(uint32_t inst)
{
if ((inst & 0xffffffe0) == 0xd5233060)
return 1;
return 0;
}
@ -288,7 +304,7 @@ int inst_A64_is_indirect_branch_link(uint32_t inst, uint8_t *is_link, struct dec
} else if ((inst & 0xffffffff) == 0xd69f03e0) {
/* ERET */
info->instr_sub_type = OCSD_S_INSTR_V8_ERET;
} else if (info->arch_version >= 0x0803) {
} else if (OCSD_IS_ARCH_MINVER(info->arch_version, ARCH_V8r3)) {
/* new pointer auth instr for v8.3 arch */
if ((inst & 0xffdff800) == 0xd71f0800) {
/* BRAA, BRAB, BLRAA, BLRBB */
@ -399,8 +415,9 @@ int inst_A64_branch_destination(uint64_t addr, uint32_t inst, uint64_t *pnpc)
{
uint64_t npc;
int is_direct_branch = 1;
if ((inst & 0xff000010) == 0x54000000) {
if ((inst & 0xff000000) == 0x54000000) {
/* B<cond> */
/* BC<cond> */
npc = addr + ((int32_t)((inst & 0x00ffffe0) << 8) >> 11);
} else if ((inst & 0x7c000000) == 0x14000000) {
/* B, BL imm */
@ -484,7 +501,7 @@ int inst_A64_is_branch_and_link(uint32_t inst, struct decode_info *info)
} else if ((inst & 0xfc000000) == 0x94000000) {
/* BL */
info->instr_sub_type = OCSD_S_INSTR_BR_LINK;
} else if (info->arch_version >= 0x0803) {
} else if (OCSD_IS_ARCH_MINVER(info->arch_version, ARCH_V8r3)) {
/* new pointer auth instr for v8.3 arch */
if ((inst & 0xfffff800) == 0xd73f0800) {
/* BLRAA, BLRBB */
@ -553,8 +570,9 @@ int inst_A64_is_conditional(uint32_t inst)
if ((inst & 0x7c000000) == 0x34000000) {
/* CB, TB */
return 1;
} else if ((inst & 0xff000010) == 0x54000000) {
} else if ((inst & 0xff000000) == 0x54000000) {
/* B.cond */
/* BC.cond */
return 1;
}
return 0;

View File

@ -119,6 +119,14 @@ ocsd_err_t TrcMemAccMapper::ReadTargetMemory(const ocsd_vaddr_t address, const u
return err;
}
void TrcMemAccMapper::InvalidateMemAccCache(const uint8_t /* cs_trace_id */)
{
// default mapper does not use cs_trace_id for cache invalidation.
if (m_cache.enabled())
m_cache.invalidateAll();
m_acc_curr = 0;
}
void TrcMemAccMapper::RemoveAllAccessors()
{
TrcMemAccessorBase *pAcc = 0;

View File

@ -101,6 +101,13 @@ DecodeTree::DecodeTree() :
{
for(int i = 0; i < 0x80; i++)
m_decode_elements[i] = 0;
// reset the global demux stats.
m_demux_stats.frame_bytes = 0;
m_demux_stats.no_id_bytes = 0;
m_demux_stats.valid_id_bytes = 0;
m_demux_stats.unknown_id_bytes = 0;
m_demux_stats.reserved_id_bytes = 0;
}
DecodeTree::~DecodeTree()
@ -486,6 +493,62 @@ ocsd_err_t DecodeTree::removeDecoder(const uint8_t CSID)
return err;
}
ocsd_err_t DecodeTree::getDecoderStats(const uint8_t CSID, ocsd_decode_stats_t **p_stats_block)
{
ocsd_err_t err = OCSD_OK;
TrcPktProcI *pPktProc = getPktProcI(CSID);
if (!pPktProc)
return OCSD_ERR_INVALID_PARAM_VAL;
err = pPktProc->getStatsBlock(p_stats_block);
if (err == OCSD_OK) {
// copy in the global demux stats.
(*p_stats_block)->demux.frame_bytes = m_demux_stats.frame_bytes;
(*p_stats_block)->demux.no_id_bytes = m_demux_stats.no_id_bytes;
(*p_stats_block)->demux.valid_id_bytes = m_demux_stats.valid_id_bytes;
(*p_stats_block)->demux.unknown_id_bytes = m_demux_stats.unknown_id_bytes;
(*p_stats_block)->demux.reserved_id_bytes = m_demux_stats.reserved_id_bytes;
}
return err;
}
ocsd_err_t DecodeTree::resetDecoderStats(const uint8_t CSID)
{
TrcPktProcI *pPktProc = getPktProcI(CSID);
if (!pPktProc)
return OCSD_ERR_INVALID_PARAM_VAL;
pPktProc->resetStats();
// reset the global demux stats.
m_demux_stats.frame_bytes = 0;
m_demux_stats.no_id_bytes = 0;
m_demux_stats.valid_id_bytes = 0;
m_demux_stats.unknown_id_bytes = 0;
m_demux_stats.reserved_id_bytes = 0;
return OCSD_OK;
}
TrcPktProcI *DecodeTree::getPktProcI(const uint8_t CSID)
{
TrcPktProcI *pPktProc = 0;
TraceComponent *pComp, *pAssoc;
DecodeTreeElement *pElem = getDecoderElement(CSID);
if (pElem)
{
pComp = pElem->getDecoderHandle();
if (pComp)
{
/* if this is a full decoder then the associated component is the packet processor */
pAssoc = pComp->getAssocComponent();
if (pAssoc)
pPktProc = dynamic_cast<TrcPktProcI *>(pAssoc);
else
pPktProc = dynamic_cast<TrcPktProcI *>(pComp);
}
}
return pPktProc;
}
DecodeTreeElement * DecodeTree::getDecoderElement(const uint8_t CSID) const
{
DecodeTreeElement *ret_elem = 0;
@ -511,7 +574,7 @@ DecodeTreeElement *DecodeTree::getNextElement(uint8_t &elemID)
if(m_decode_elem_iter < 0x80)
{
// find a none zero entry or end of range
while((m_decode_elements[m_decode_elem_iter] == 0) && (m_decode_elem_iter < 0x80))
while((m_decode_elem_iter < 0x80) && (m_decode_elements[m_decode_elem_iter] == 0))
m_decode_elem_iter++;
// return entry unless end of range
@ -527,7 +590,7 @@ DecodeTreeElement *DecodeTree::getNextElement(uint8_t &elemID)
bool DecodeTree::initialise(const ocsd_dcd_tree_src_t type, uint32_t formatterCfgFlags)
{
bool initOK = true;
ocsd_err_t err;
m_dcd_tree_type = type;
if(type == OCSD_TRC_SRC_FRAME_FORMATTED)
{
@ -535,14 +598,19 @@ bool DecodeTree::initialise(const ocsd_dcd_tree_src_t type, uint32_t formatterCf
m_frame_deformatter_root = new (std::nothrow) TraceFormatterFrameDecoder();
if(m_frame_deformatter_root)
{
m_frame_deformatter_root->Configure(formatterCfgFlags);
if (m_frame_deformatter_root->Init() != OCSD_OK)
return false;
m_frame_deformatter_root->getErrLogAttachPt()->attach(DecodeTree::s_i_error_logger);
err = m_frame_deformatter_root->Configure(formatterCfgFlags);
if (err != OCSD_OK)
return false;
m_i_decoder_root = dynamic_cast<ITrcDataIn*>(m_frame_deformatter_root);
m_frame_deformatter_root->SetDemuxStatsBlock(&m_demux_stats);
}
else
initOK = false;
return false;
}
return initOK;
return true;
}
void DecodeTree::setSingleRoot(TrcPktProcI *pComp)
@ -621,6 +689,7 @@ ocsd_err_t DecodeTree::addPacketPrinter(uint8_t CSID, bool bMonitor, ItemPrinter
switch (protocol)
{
case OCSD_PROTOCOL_ETMV4I:
case OCSD_PROTOCOL_ETE:
{
PacketPrinter<EtmV4ITrcPacket> *pTPrinter = dynamic_cast<PacketPrinter<EtmV4ITrcPacket> *>(pPrinter);
if (bMonitor)

View File

@ -229,4 +229,25 @@ void ocsdError::appendErrorDetails(std::string &errStr, const ocsdError &error)
errStr = oss.str();
}
const char* ocsdDataRespStr::getStr()
{
static const char* szRespStr[] = {
"OCSD_RESP_CONT: Continue processing.",
"OCSD_RESP_WARN_CONT: Continue processing -> a component logged a warning.",
"OCSD_RESP_ERR_CONT: Continue processing -> a component logged an error.",
"OCSD_RESP_WAIT: Pause processing",
"OCSD_RESP_WARN_WAIT: Pause processing -> a component logged a warning.",
"OCSD_RESP_ERR_WAIT: Pause processing -> a component logged an error.",
"OCSD_RESP_FATAL_NOT_INIT: Processing Fatal Error : component unintialised.",
"OCSD_RESP_FATAL_INVALID_OP: Processing Fatal Error : invalid data path operation.",
"OCSD_RESP_FATAL_INVALID_PARAM: Processing Fatal Error : invalid parameter in datapath call.",
"OCSD_RESP_FATAL_INVALID_DATA: Processing Fatal Error : invalid trace data.",
"OCSD_RESP_FATAL_SYS_ERR: Processing Fatal Error : internal system error."
};
if ((m_type < OCSD_RESP_CONT) || (m_type > OCSD_RESP_FATAL_SYS_ERR))
return "Unknown OCSD_RESP type.";
return szRespStr[m_type];
}
/* End of File ocsd_error.cpp */

View File

@ -42,6 +42,7 @@ OcsdGenElemStack::OcsdGenElemStack() :
m_curr_elem_idx(0),
m_send_elem_idx(0),
m_CSID(0),
m_sendIf(NULL),
m_is_init(false)
{

View File

@ -39,13 +39,15 @@
#include "opencsd/etmv3/trc_dcd_mngr_etmv3.h"
#include "opencsd/ptm/trc_dcd_mngr_ptm.h"
#include "opencsd/stm/trc_dcd_mngr_stm.h"
#include "opencsd/ete/trc_dcd_mngr_ete.h"
// create array of built-in decoders to register with library
static built_in_decoder_info_t sBuiltInArray[] = {
CREATE_BUILTIN_ENTRY(DecoderMngrEtmV4I,OCSD_BUILTIN_DCD_ETMV4I),
CREATE_BUILTIN_ENTRY(DecoderMngrEtmV3, OCSD_BUILTIN_DCD_ETMV3),
CREATE_BUILTIN_ENTRY(DecoderMngrPtm, OCSD_BUILTIN_DCD_PTM),
CREATE_BUILTIN_ENTRY(DecoderMngrStm, OCSD_BUILTIN_DCD_STM)
CREATE_BUILTIN_ENTRY(DecoderMngrStm, OCSD_BUILTIN_DCD_STM),
CREATE_BUILTIN_ENTRY(DecoderMngrETE, OCSD_BUILTIN_DCD_ETE)
//{ 0, 0, 0}
};
@ -90,7 +92,6 @@ OcsdLibDcdRegister::~OcsdLibDcdRegister()
m_pLastTypedDecoderMngr = 0;
}
const ocsd_err_t OcsdLibDcdRegister::registerDecoderTypeByName(const std::string &name, IDecoderMngr *p_decoder_fact)
{
if(isRegisteredDecoder(name))

View File

@ -55,8 +55,9 @@ ItemPrinter *PktPrinterFact::createProtocolPrinter(std::vector<ItemPrinter *> &p
{
ItemPrinter *pPrinter = 0;
switch (protocol)
{
{
case OCSD_PROTOCOL_ETMV4I:
case OCSD_PROTOCOL_ETE:
pPrinter = new (std::nothrow) PacketPrinter<EtmV4ITrcPacket>(CSID);
break;
case OCSD_PROTOCOL_ETMV3:

View File

@ -224,6 +224,7 @@ void TrcPktProcPtm::InitProcessorState()
m_waitASyncSOPkt = false;
m_bAsyncRawOp = false;
m_bOPNotSyncPkt = false;
m_excepAltISA = 0;
m_curr_packet.ResetState();
InitPacketState();
@ -559,7 +560,7 @@ void TrcPktProcPtm::pktWPointUpdate()
m_gotExcepBytes = false; // mark as not got all required exception bytes thus far
m_numExcepBytes = 0; // 0 read in
m_addrPktIsa = ocsd_isa_unknown; // not set by this packet as yet
m_addrPktIsa = ocsd_isa_unknown; // not set by this packet as yet
}
// collect all the bytes needed
@ -567,10 +568,12 @@ void TrcPktProcPtm::pktWPointUpdate()
{
if(readByte(currByte))
{
byteIdx = m_currPacketData.size() - 1;
if(!m_gotAddrBytes)
{
if(byteIdx < 4)
// byteIdx for address byte will run from 1 to 5 - first 4 my have continuation or not.
if(byteIdx <= 4)
{
// address bytes 1 - 4;
// ISA stays the same

View File

@ -72,17 +72,6 @@ static ap_map_elem_t ap_map_array[] =
{ "Cortex-M4", { ARCH_V7, profile_CortexM } }
};
static ap_map_elem_t arch_map_array[] =
{
{ "ARMv7-A", { ARCH_V7, profile_CortexA } },
{ "ARMv7-R", { ARCH_V7, profile_CortexR } },
{ "ARMv7-M", { ARCH_V7, profile_CortexM } },
{ "ARMv8-A", { ARCH_V8, profile_CortexA } },
{ "ARMv8.3-A", { ARCH_V8r3, profile_CortexA } },
{ "ARMv8-R", { ARCH_V8, profile_CortexR } },
{ "ARMv8-M", { ARCH_V8, profile_CortexM } },
};
CoreArchProfileMap::CoreArchProfileMap()
{
unsigned i;
@ -90,10 +79,99 @@ CoreArchProfileMap::CoreArchProfileMap()
{
core_profiles[ap_map_array[i].name] = ap_map_array[i].ap;
}
for (i = 0; i < sizeof(arch_map_array) / sizeof(_ap_map_elements); i++)
{
arch_profiles[arch_map_array[i].name] = arch_map_array[i].ap;
}
}
ocsd_arch_profile_t CoreArchProfileMap::getArchProfile(const std::string &coreName)
{
ocsd_arch_profile_t ap = { ARCH_UNKNOWN, profile_Unknown };
bool bFound = false;
std::map<std::string, ocsd_arch_profile_t>::const_iterator it;
/* match against the core name map. */
it = core_profiles.find(coreName);
if (it != core_profiles.end())
{
ap = it->second;
bFound = true;
}
/* try a pattern match on core name - pick up ARMvM[.m]-P and ARM-{aa|AA}64[-P] */
if (!bFound)
ap = getPatternMatchCoreName(coreName);
return ap;
}
ocsd_arch_profile_t CoreArchProfileMap::getPatternMatchCoreName(const std::string &coreName)
{
ocsd_arch_profile_t ap = { ARCH_UNKNOWN, profile_Unknown };
size_t pos;
/* look for ARMvM[.m]-P */
pos = coreName.find("ARMv");
if (pos == 0)
{
int majver = coreName[4] - '0';
int minver = 0;
int dotoffset = 0;
pos = coreName.find_first_of(".");
if (pos == 5) {
minver = coreName[6] - '0';
dotoffset = 2;
}
else if (pos != std::string::npos)
return ap;
if (majver == 7)
ap.arch = ARCH_V7;
else if (majver >= 8) {
ap.arch = ARCH_AA64; /* default to 8.3+*/
if (majver == 8) {
if (minver < 3)
ap.arch = ARCH_V8;
else if (minver == 3)
ap.arch = ARCH_V8r3;
}
}
else
return ap; /* no valid version - return unknown */
if (coreName.find_first_of("-", 4) == (size_t)(5 + dotoffset)) {
int profile_idx = 6 + dotoffset;
if (coreName[profile_idx] == 'A')
ap.profile = profile_CortexA;
else if (coreName[profile_idx] == 'R')
ap.profile = profile_CortexR;
else if (coreName[profile_idx] == 'M')
ap.profile = profile_CortexM;
else
ap.arch = ARCH_UNKNOWN; /*reset arch, return unknown*/
}
else
ap.arch = ARCH_UNKNOWN; /*reset arch, return unknown*/
return ap;
}
/* look for ARM-{AA|aa}64[-P] */
pos = coreName.find("ARM-");
if (pos == 0)
{
pos = coreName.find("aa64");
if (pos != 4)
pos = coreName.find("AA64");
if (pos == 4)
{
ap.arch = ARCH_AA64;
ap.profile = profile_CortexA;
if (coreName.find_first_of("-", 7) == 8) {
if (coreName[9] == 'R')
ap.profile = profile_CortexR;
else if (coreName[9] == 'M')
ap.profile = profile_CortexM;
}
}
}
return ap;
}
/* End of File trc_core_arch_map.cpp */

View File

@ -54,7 +54,8 @@ TraceFmtDcdImpl::TraceFmtDcdImpl() : TraceComponent(DEFORMATTER_NAME),
m_use_force_sync(false),
m_alignment(16), // assume frame aligned data as default.
m_b_output_packed_raw(false),
m_b_output_unpacked_raw(false)
m_b_output_unpacked_raw(false),
m_pStatsBlock(0)
{
resetStateParams();
@ -244,7 +245,12 @@ ocsd_datapath_resp_t TraceFmtDcdImpl::processTraceData(
if(m_trc_curr_idx != index) // none continuous trace data - throw an error.
throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_DFMTR_NOTCONTTRACE,index);
}
// record the incoming block for extraction routines to use.
m_in_block_base = pDataBlock;
m_in_block_size = dataBlockSize;
m_in_block_processed = 0;
if(dataBlockSize % m_alignment) // must be correctly aligned data
{
ocsdError err(OCSD_ERR_SEV_ERROR, OCSD_ERR_INVALID_PARAM_VAL);
@ -254,11 +260,6 @@ ocsd_datapath_resp_t TraceFmtDcdImpl::processTraceData(
throw ocsdError(&err);
}
// record the incoming block for extraction routines to use.
m_in_block_base = pDataBlock;
m_in_block_size = dataBlockSize;
m_in_block_processed = 0;
// processing loop...
if(checkForSync())
{
@ -324,12 +325,18 @@ ocsd_err_t TraceFmtDcdImpl::DecodeConfigure(uint32_t flags)
}
else
{
// alightment is the multiple of bytes the buffer size must be.
m_cfgFlags = flags;
// using memory aligned buffers, the formatter always outputs 16 byte frames so enforce
// this on the input
m_alignment = 16;
if(flags & OCSD_DFRMTR_HAS_FSYNCS)
m_alignment = 4;
else if(flags & OCSD_DFRMTR_HAS_HSYNCS)
// if we have HSYNCS then always align to 2 byte buffers
if(flags & OCSD_DFRMTR_HAS_HSYNCS)
m_alignment = 2;
// otherwise FSYNCS only can have 4 byte aligned buffers.
else if(flags & OCSD_DFRMTR_HAS_FSYNCS)
m_alignment = 4;
}
return err;
}
@ -344,6 +351,7 @@ void TraceFmtDcdImpl::resetStateParams()
// current frame processing
m_ex_frm_n_bytes = 0;
m_b_fsync_start_eob = false;
m_trc_curr_idx_sof = OCSD_BAD_TRC_INDEX;
}
@ -415,20 +423,23 @@ void TraceFmtDcdImpl::outputUnsyncedBytes(uint32_t /*num_bytes*/)
//**TBD:
}
int TraceFmtDcdImpl::checkForResetFSyncPatterns()
ocsd_err_t TraceFmtDcdImpl::checkForResetFSyncPatterns(uint32_t &f_sync_bytes)
{
const uint32_t FSYNC_PATTERN = 0x7FFFFFFF; // LE host pattern for FSYNC
bool check_for_fsync = true;
int num_fsyncs = 0;
const uint8_t *dataPtr = m_in_block_base + m_in_block_processed;
uint32_t bytes_processed = m_in_block_processed;
const uint8_t *dataPtr = m_in_block_base + bytes_processed;
ocsd_err_t err = OCSD_OK;
while (check_for_fsync && (m_in_block_processed < m_in_block_size))
while (check_for_fsync && (bytes_processed < m_in_block_size))
{
// look for consecutive fsyncs as padding or for reset downstream - both cases will reset downstream....
if (*((uint32_t *)(dataPtr)) == FSYNC_PATTERN)
{
dataPtr += sizeof(uint32_t);
num_fsyncs++;
num_fsyncs++;
bytes_processed += sizeof(uint32_t);
}
else
check_for_fsync = false;
@ -436,7 +447,6 @@ int TraceFmtDcdImpl::checkForResetFSyncPatterns()
if (num_fsyncs)
{
printf("Frame deformatter: Found %d FSYNCS\n",num_fsyncs);
if ((num_fsyncs % 4) == 0)
{
// reset the upstream decoders
@ -449,32 +459,40 @@ int TraceFmtDcdImpl::checkForResetFSyncPatterns()
}
else
{
// TBD: throw processing error, none frame size block of fsyncs
err = OCSD_ERR_DFMTR_BAD_FHSYNC;
}
}
return num_fsyncs * 4;
f_sync_bytes += num_fsyncs * 4;
return err;
}
/* Extract a single frame from the input buffer. */
bool TraceFmtDcdImpl::extractFrame()
{
const uint32_t FSYNC_PATTERN = 0x7FFFFFFF; // LE host pattern for FSYNC
const uint16_t HSYNC_PATTERN = 0x7FFF; // LE host pattern for HSYNC
const uint16_t FSYNC_START = 0xFFFF; // LE host pattern for start 2 bytes of fsync
bool cont_process = true; // continue processing after extraction.
ocsd_err_t err;
uint32_t f_sync_bytes = 0; // skipped f sync bytes
uint32_t h_sync_bytes = 0; // skipped h sync bytes
uint32_t ex_bytes = 0; // extracted this pass (may be filling out part frame)
uint32_t buf_left = m_in_block_size - m_in_block_processed; // bytes remaining in buffer this pass.
// memory aligned sources are always multiples of frames, aligned to start.
// last call was end of input block - but carried on to process full frame.
// exit early here.
if (!buf_left)
return false;
// memory aligned input data is forced to be always multiples of 16 byte frames, aligned to start.
if( m_cfgFlags & OCSD_DFRMTR_FRAME_MEM_ALIGN)
{
// some linux drivers (e.g. for perf) will insert FSYNCS to pad or differentiate
// between blocks of aligned data, always in frame aligned complete 16 byte frames.
// between blocks of aligned data, always in frame aligned complete 16 byte frames.
// we need to skip past these frames, resetting as we go.
if (m_cfgFlags & OCSD_DFRMTR_RESET_ON_4X_FSYNC)
{
f_sync_bytes = checkForResetFSyncPatterns();
err = checkForResetFSyncPatterns(f_sync_bytes);
/* in this case the FSYNC pattern is output on both packed and unpacked cases */
if (f_sync_bytes && (m_b_output_packed_raw || m_b_output_unpacked_raw))
@ -486,77 +504,96 @@ bool TraceFmtDcdImpl::extractFrame()
m_in_block_base + m_in_block_processed,
0);
}
// throw processing error, none frame size block of fsyncs
if (err)
throw ocsdError(OCSD_ERR_SEV_ERROR, err, m_trc_curr_idx, "Incorrect FSYNC frame reset pattern");
buf_left -= f_sync_bytes;
}
if((m_in_block_processed+f_sync_bytes) == m_in_block_size)
if (buf_left)
{
m_ex_frm_n_bytes = 0;
cont_process = false; // end of input data.
}
else
{
// always a complete frame.
m_ex_frm_n_bytes = OCSD_DFRMTR_FRAME_SIZE;
memcpy(m_ex_frm_data, m_in_block_base + m_in_block_processed + f_sync_bytes, m_ex_frm_n_bytes);
m_trc_curr_idx_sof = m_trc_curr_idx + f_sync_bytes;
ex_bytes = OCSD_DFRMTR_FRAME_SIZE;
// always a complete frame - the input data has to be 16 byte multiple alignment.
m_ex_frm_n_bytes = OCSD_DFRMTR_FRAME_SIZE;
memcpy(m_ex_frm_data, m_in_block_base + m_in_block_processed + f_sync_bytes, m_ex_frm_n_bytes);
m_trc_curr_idx_sof = m_trc_curr_idx + f_sync_bytes;
ex_bytes = OCSD_DFRMTR_FRAME_SIZE;
}
}
else
{
// extract data accounting for frame syncs and hsyncs if present.
// we know we are aligned at this point - could be FSYNC or HSYNCs here.
// HSYNC present, library forces input to be aligned 2 byte multiples
// FSYNC - w/o HSYNCs, forces input to be aligned 4 byte multiples.
// check what we a looking for
bool hasFSyncs = ((m_cfgFlags & OCSD_DFRMTR_HAS_FSYNCS) == OCSD_DFRMTR_HAS_FSYNCS);
bool hasHSyncs = ((m_cfgFlags & OCSD_DFRMTR_HAS_HSYNCS) == OCSD_DFRMTR_HAS_HSYNCS);
bool hasFSyncs = ((m_cfgFlags & OCSD_DFRMTR_HAS_FSYNCS) == OCSD_DFRMTR_HAS_FSYNCS);
bool hasHSyncs = ((m_cfgFlags & OCSD_DFRMTR_HAS_HSYNCS) == OCSD_DFRMTR_HAS_HSYNCS);
const uint8_t* dataPtr = m_in_block_base + m_in_block_processed;
uint16_t data_pair_val;
const uint8_t *dataPtr = m_in_block_base+m_in_block_processed;
const uint8_t *eodPtr = m_in_block_base+m_in_block_size;
cont_process = (bool)(dataPtr < eodPtr);
// can have FSYNCS at start of frame (in middle is an error).
if(hasFSyncs && cont_process && (m_ex_frm_n_bytes == 0))
if (hasFSyncs && (m_ex_frm_n_bytes == 0))
{
while((*((uint32_t *)(dataPtr)) == FSYNC_PATTERN) && cont_process)
// was there an fsync start at the end of the last buffer?
if (m_b_fsync_start_eob) {
// last 2 of FSYNC look like HSYNC
if (*(uint16_t*)(dataPtr) != HSYNC_PATTERN)
{
// this means 0xFFFF followed by something else - invalid ID + ????
throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_DFMTR_BAD_FHSYNC, m_trc_curr_idx, "Bad FSYNC pattern before frame or invalid ID.(0x7F)");
}
else
{
f_sync_bytes += 2;
buf_left -= 2;
dataPtr += 2;
}
m_b_fsync_start_eob = false;
}
// regular fsync checks
while ((buf_left >= 4) && (*((uint32_t*)(dataPtr)) == FSYNC_PATTERN))
{
f_sync_bytes += 4;
dataPtr += 4;
cont_process = (bool)(dataPtr < eodPtr);
buf_left -= 4;
}
// handle possible part fsync at the end of a buffer
if (buf_left == 2)
{
if (*(uint16_t*)(dataPtr) == FSYNC_START)
{
f_sync_bytes += 2;
buf_left -= 2;
dataPtr += 2;
m_b_fsync_start_eob = true;
}
}
}
// not an FSYNC
while((m_ex_frm_n_bytes < OCSD_DFRMTR_FRAME_SIZE) && cont_process)
// process remaining data in pairs of bytes
while ((m_ex_frm_n_bytes < OCSD_DFRMTR_FRAME_SIZE) && buf_left)
{
// check for illegal out of sequence FSYNC
if((m_ex_frm_n_bytes % 4) == 0)
{
if(*((uint32_t *)(dataPtr)) == FSYNC_PATTERN)
{
// throw an illegal FSYNC error
throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_DFMTR_BAD_FHSYNC, m_trc_curr_idx, "Bad FSYNC in frame.");
}
}
// mark start of frame after FSyncs
if(m_ex_frm_n_bytes == 0)
if (m_ex_frm_n_bytes == 0)
m_trc_curr_idx_sof = m_trc_curr_idx + f_sync_bytes;
m_ex_frm_data[m_ex_frm_n_bytes] = dataPtr[0];
m_ex_frm_data[m_ex_frm_n_bytes+1] = dataPtr[1];
m_ex_frm_n_bytes+=2;
ex_bytes +=2;
m_ex_frm_data[m_ex_frm_n_bytes + 1] = dataPtr[1];
data_pair_val = *((uint16_t*)(dataPtr));
// check pair is not HSYNC
if(*((uint16_t *)(dataPtr)) == HSYNC_PATTERN)
if (data_pair_val == HSYNC_PATTERN)
{
if(hasHSyncs)
if (hasHSyncs)
{
m_ex_frm_n_bytes-=2;
ex_bytes -= 2;
h_sync_bytes+=2;
h_sync_bytes += 2;
}
else
{
@ -564,22 +601,27 @@ bool TraceFmtDcdImpl::extractFrame()
throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_DFMTR_BAD_FHSYNC, m_trc_curr_idx, "Bad HSYNC in frame.");
}
}
// can't have a start of FSYNC here / illegal trace ID
else if (data_pair_val == FSYNC_START)
{
throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_DFMTR_BAD_FHSYNC, m_trc_curr_idx, "Bad FSYNC start in frame or invalid ID (0x7F).");
}
else
{
m_ex_frm_n_bytes += 2;
ex_bytes += 2;
}
buf_left -= 2;
dataPtr += 2;
cont_process = (bool)(dataPtr < eodPtr);
}
// if we hit the end of data but still have a complete frame waiting,
// need to continue processing to allow it to be used.
if(!cont_process && (m_ex_frm_n_bytes == OCSD_DFRMTR_FRAME_SIZE))
cont_process = true;
}
// total bytes processed this pass
uint32_t total_processed = ex_bytes + f_sync_bytes + h_sync_bytes;
// output raw data on raw frame channel - packed raw.
if (((m_ex_frm_n_bytes == OCSD_DFRMTR_FRAME_SIZE) || !cont_process) && m_b_output_packed_raw)
if (((m_ex_frm_n_bytes == OCSD_DFRMTR_FRAME_SIZE) || (buf_left == 0)) && m_b_output_packed_raw)
{
outputRawMonBytes( OCSD_OP_DATA,
m_trc_curr_idx,
@ -595,7 +637,11 @@ bool TraceFmtDcdImpl::extractFrame()
// update index past the processed data
m_trc_curr_idx += total_processed;
return cont_process;
// update any none trace data byte stats
addToFrameStats((uint64_t)(f_sync_bytes + h_sync_bytes));
// if we are exiting with a full frame then signal processing to continue
return (bool)(m_ex_frm_n_bytes == OCSD_DFRMTR_FRAME_SIZE);
}
bool TraceFmtDcdImpl::unpackFrame()
@ -604,6 +650,7 @@ bool TraceFmtDcdImpl::unpackFrame()
uint8_t frameFlagBit = 0x1;
uint8_t newSrcID = OCSD_BAD_CS_SRC_ID;
bool PrevIDandIDChange = false;
uint64_t noneDataBytes = 0;
// init output processing
m_out_data_idx = 0;
@ -650,6 +697,7 @@ bool TraceFmtDcdImpl::unpackFrame()
/// TBD - ID indexing in here.
}
noneDataBytes++;
}
else
// it's just data
@ -671,6 +719,7 @@ bool TraceFmtDcdImpl::unpackFrame()
{
// no matter if change or not, no associated data in byte 15 anyway so just set.
m_curr_src_ID = (m_ex_frm_data[14] >> 1) & 0x7f;
noneDataBytes++;
}
// it's data
else
@ -678,6 +727,9 @@ bool TraceFmtDcdImpl::unpackFrame()
m_out_data[m_out_data_idx].data[m_out_data[m_out_data_idx].valid++] = m_ex_frm_data[14] | ((frameFlagBit & m_ex_frm_data[15]) ? 0x1 : 0x0);
}
m_ex_frm_n_bytes = 0; // mark frame as empty;
noneDataBytes++; // byte 15 is always non-data.
addToFrameStats(noneDataBytes); // update the non data byte stats.
return true;
}
@ -716,6 +768,8 @@ bool TraceFmtDcdImpl::outputFrame()
m_out_data[m_out_processed].data + m_out_data[m_out_processed].used,
&bytes_used));
addToIDStats((uint64_t)bytes_used);
if(!dataPathCont())
{
cont_processing = false;
@ -739,7 +793,12 @@ bool TraceFmtDcdImpl::outputFrame()
m_out_data[m_out_processed].valid,
m_out_data[m_out_processed].data,
m_out_data[m_out_processed].id);
}
}
if (isReservedID(m_out_data[m_out_processed].id))
addToReservedIDStats((uint64_t)m_out_data[m_out_processed].valid);
else
addToNoIDStats((uint64_t)m_out_data[m_out_processed].valid);
m_out_processed++; // skip past this data.
}
}
@ -754,13 +813,44 @@ bool TraceFmtDcdImpl::outputFrame()
m_out_data[m_out_processed].valid,
m_out_data[m_out_processed].data,
m_out_data[m_out_processed].id);
}
}
addToUnknownIDStats((uint64_t)m_out_data[m_out_processed].valid);
m_out_processed++; // skip past this data.
}
}
return cont_processing;
}
void TraceFmtDcdImpl::addToIDStats(uint64_t val)
{
if (m_pStatsBlock)
m_pStatsBlock->valid_id_bytes += val;
}
void TraceFmtDcdImpl::addToNoIDStats(uint64_t val)
{
if (m_pStatsBlock)
m_pStatsBlock->no_id_bytes += val;
}
void TraceFmtDcdImpl::addToFrameStats(uint64_t val)
{
if (m_pStatsBlock)
m_pStatsBlock->frame_bytes += val;
}
void TraceFmtDcdImpl::addToUnknownIDStats(uint64_t val)
{
if (m_pStatsBlock)
m_pStatsBlock->unknown_id_bytes += val;
}
void TraceFmtDcdImpl::addToReservedIDStats(uint64_t val)
{
if (m_pStatsBlock)
m_pStatsBlock->reserved_id_bytes += val;
}
/***************************************************************/
/* interface */
/***************************************************************/
@ -819,21 +909,27 @@ componentAttachPt<ITraceErrorLog> *TraceFormatterFrameDecoder::getErrLogAttachPt
return (m_pDecoder != 0) ? m_pDecoder->getErrorLogAttachPt() : 0;
}
/* configuration - set operational mode for incoming stream (has FSYNCS etc) */
ocsd_err_t TraceFormatterFrameDecoder::Configure(uint32_t cfg_flags)
ocsd_err_t TraceFormatterFrameDecoder::Init()
{
if(!m_pDecoder)
{
if(m_instNum >= 0)
if (!m_pDecoder)
{
if (m_instNum >= 0)
m_pDecoder = new (std::nothrow) TraceFmtDcdImpl(m_instNum);
else
m_pDecoder = new (std::nothrow) TraceFmtDcdImpl();
if(!m_pDecoder) return OCSD_ERR_MEM;
if (!m_pDecoder) return OCSD_ERR_MEM;
}
m_pDecoder->DecodeConfigure(cfg_flags);
return OCSD_OK;
}
/* configuration - set operational mode for incoming stream (has FSYNCS etc) */
ocsd_err_t TraceFormatterFrameDecoder::Configure(uint32_t cfg_flags)
{
if (!m_pDecoder)
return OCSD_ERR_NOT_INIT;
return m_pDecoder->DecodeConfigure(cfg_flags);
}
const uint32_t TraceFormatterFrameDecoder::getConfigFlags() const
{
uint32_t flags = 0;
@ -865,5 +961,10 @@ ocsd_datapath_resp_t TraceFormatterFrameDecoder::Flush()
return (m_pDecoder == 0) ? OCSD_RESP_FATAL_NOT_INIT : m_pDecoder->Flush();
}
void TraceFormatterFrameDecoder::SetDemuxStatsBlock(ocsd_demux_stats_t *pStatsBlock)
{
if (m_pDecoder)
m_pDecoder->SetDemuxStatsBlock(pStatsBlock);
}
/* End of File trc_frame_deformatter.cpp */

View File

@ -75,6 +75,8 @@ private:
ocsd_err_t DecodeConfigure(uint32_t flags);
ocsd_err_t SetForcedSyncIndex(ocsd_trc_index_t index, bool bSet);
void SetDemuxStatsBlock(ocsd_demux_stats_t *pStatsBlock) { m_pStatsBlock = pStatsBlock; };
private:
ocsd_datapath_resp_t executeNoneDataOpAllIDs(ocsd_datapath_op_t op, const ocsd_trc_index_t index = 0);
ocsd_datapath_resp_t processTraceData(const ocsd_trc_index_t index,
@ -113,12 +115,20 @@ private:
void setRawChanFilterAll(bool bEnable);
const bool rawChanEnabled(const uint8_t id) const;
int checkForResetFSyncPatterns();
ocsd_err_t checkForResetFSyncPatterns(uint32_t &f_sync_bytes);
friend class TraceFormatterFrameDecoder;
// attachment points
// stats updates
void addToIDStats(uint64_t val);
void addToNoIDStats(uint64_t val);
void addToFrameStats(uint64_t val);
void addToUnknownIDStats(uint64_t val);
void addToReservedIDStats(uint64_t val);
bool isReservedID(uint8_t ID) { return ((ID == 0) || (ID >= 0x70)); };
// attachment points
componentAttachPt<ITrcDataIn> m_IDStreams[128];
componentAttachPt<ITrcRawFrameIn> m_RawTraceFrame;
@ -142,12 +152,18 @@ private:
// incoming frame buffer
uint8_t m_ex_frm_data[OCSD_DFRMTR_FRAME_SIZE]; // buffer the current frame in case we have to stop part way through
int m_ex_frm_n_bytes; // number of valid bytes in the current frame (extraction)
bool m_b_fsync_start_eob; // flag to indicate that the end of the last buffer was a pair of bytes
// (0xffff) that could only validly be the start and FSYNC.
ocsd_trc_index_t m_trc_curr_idx_sof; // trace source index at start of frame.
// channel output data - can never be more than a frame of data for a single ID.
out_chan_data m_out_data[7]; // can only be 8 ID changes in a frame, but last on has no associated data so 7 possible data blocks
/* channel output data - can never be more than a frame of data for a single ID.
* 8 possible ID changes per frame. Although the final one can have no associated data, a pathological
* case exists with 7 ID changes, all data associated with a previous frame, except for last
* ID / data byte which is data. Not possible with normal hardware but guard against corrupt input.
*/
out_chan_data m_out_data[8]; // output data for a given ID
int m_out_data_idx; // number of out_chan_data frames used.
int m_out_processed; // number of complete out_chan_data frames output.
int m_out_processed; // number of complete out_chan_data frames output.
/* local copy of input buffer pointers*/
const uint8_t *m_in_block_base;
@ -159,6 +175,8 @@ private:
bool m_b_output_unpacked_raw;
bool m_raw_chan_enable[128];
ocsd_demux_stats_t *m_pStatsBlock;
};

View File

@ -54,7 +54,10 @@ static const char *s_elem_descs[][2] =
{"OCSD_GEN_TRC_ELEM_TIMESTAMP","Timestamp - preceding elements happeded before this time."},
{"OCSD_GEN_TRC_ELEM_CYCLE_COUNT","Cycle count - cycles since last cycle count value - associated with a preceding instruction range."},
{"OCSD_GEN_TRC_ELEM_EVENT","Event - numbered event or trigger"},
{"OCSD_GEN_TRC_ELEM_SWTRACE","Software trace packet - may contain data payload."},
{"OCSD_GEN_TRC_ELEM_SWTRACE","Software trace packet - may contain data payload. STM / ITM hardware trace with channel protocol."},
{"OCSD_GEN_TRC_ELEM_SYNC_MARKER","Synchronisation marker - marks position in stream of an element that is output later."},
{"OCSD_GEN_TRC_ELEM_MEMTRANS","Trace indication of transactional memory operations."},
{"OCSD_GEN_TRC_ELEM_INSTRUMENTATION", "PE instrumentation trace - PE generated SW trace, application dependent protocol."},
{"OCSD_GEN_TRC_ELEM_CUSTOM","Fully custom packet type."}
};
@ -64,7 +67,8 @@ static const char *instr_type[] = {
"iBR ",
"ISB ",
"DSB.DMB",
"WFI.WFE"
"WFI.WFE",
"TSTART"
};
#define T_SIZE (sizeof(instr_type) / sizeof(const char *))
@ -105,6 +109,16 @@ static const char *s_unsync_reason[] = {
"bad-packet", // UNSYNC_BAD_PACKET - bad packet at input - resync to restart.
"end-of-trace", // UNSYNC_EOT - end of trace info.
};
static const char *s_transaction_type[] = {
"Init",
"Start",
"Commit",
"Fail"
};
static const char *s_marker_t[] = {
"Timestamp marker", // ELEM_MARKER_TS
};
void OcsdTraceElement::toString(std::string &str) const
{
@ -158,7 +172,14 @@ void OcsdTraceElement::toString(std::string &str) const
{
oss << "EL" << std::dec << (int)(context.exception_level);
}
oss << (context.security_level == ocsd_sec_secure ? "S; " : "N; ") << (context.bits64 ? "64-bit; " : "32-bit; ");
switch (context.security_level)
{
case ocsd_sec_secure: oss << "S; "; break;
case ocsd_sec_nonsecure: oss << "N; "; break;
case ocsd_sec_root: oss << "Root; "; break;
case ocsd_sec_realm: oss << "Realm; "; break;
}
oss << (context.bits64 ? "64-bit; " : "32-bit; ");
if(context.vmid_valid)
oss << "VMID=0x" << std::hex << context.vmid << "; ";
if(context.ctxt_id_valid)
@ -190,6 +211,19 @@ void OcsdTraceElement::toString(std::string &str) const
oss << " [" << s_unsync_reason[unsync_eot_info] << "]";
break;
case OCSD_GEN_TRC_ELEM_SYNC_MARKER:
oss << " [" << s_marker_t[sync_marker.type] << "(0x" << std::setfill('0') << std::setw(8) << std::hex << sync_marker.value << ")]";
break;
case OCSD_GEN_TRC_ELEM_MEMTRANS:
if (mem_trans <= OCSD_MEM_TRANS_FAIL)
oss << s_transaction_type[mem_trans];
break;
case OCSD_GEN_TRC_ELEM_INSTRUMENTATION:
oss << "EL" << std::dec << (int)sw_ite.el << "; 0x" << std::setfill('0') << std::setw(16) << std::hex << sw_ite.value;
break;
default: break;
}
if(has_cc)

View File

@ -52,8 +52,6 @@ void trcPrintableElem::getValStr(std::string &valStr, const int valTotalBitSize,
assert((valTotalBitSize >= 4) && (valTotalBitSize <= 64));
uint64_t LimitMask = ~0ULL;
LimitMask >>= 64-valTotalBitSize;
valStr = "0x";
if(asHex)