On 3 June 2016 at 02:26, Mike Leach <mike.leach@linaro.org> wrote:
Please provide a description of the changes presented this patch.
Can I suggest ocsd_ELERR ?
> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> ---
> .../ref_trace_decode_lib.vcxproj | 2 +
> .../ref_trace_decode_lib.vcxproj.filters | 6 +
> decoder/include/common/ocsd_code_follower.h | 225 +++++++++++++++++++++
> decoder/include/common/ocsd_pe_context.h | 4 +-
> decoder/include/ocsd_if_types.h | 2 +
> decoder/source/ocsd_code_follower.cpp | 155 ++++++++++++++
> 6 files changed, 392 insertions(+), 2 deletions(-)
> create mode 100644 decoder/include/common/ocsd_code_follower.h
> create mode 100644 decoder/source/ocsd_code_follower.cpp
>
> diff --git a/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj b/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj
> index 07aad23..2dc5f0c 100644
> --- a/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj
> +++ b/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj
> @@ -304,6 +304,7 @@
> <ItemGroup>
> <ClInclude Include="..\..\..\include\common\comp_attach_notifier_i.h" />
> <ClInclude Include="..\..\..\include\common\comp_attach_pt_t.h" />
> + <ClInclude Include="..\..\..\include\common\ocsd_code_follower.h" />
> <ClInclude Include="..\..\..\include\common\ocsd_dcd_tree.h" />
> <ClInclude Include="..\..\..\include\common\ocsd_dcd_tree_elem.h" />
> <ClInclude Include="..\..\..\include\common\ocsd_error.h" />
> @@ -390,6 +391,7 @@
> <ClCompile Include="..\..\..\source\mem_acc\trc_mem_acc_cb.cpp" />
> <ClCompile Include="..\..\..\source\mem_acc\trc_mem_acc_file.cpp" />
> <ClCompile Include="..\..\..\source\mem_acc\trc_mem_acc_mapper.cpp" />
> + <ClCompile Include="..\..\..\source\ocsd_code_follower.cpp" />
> <ClCompile Include="..\..\..\source\ocsd_dcd_tree.cpp" />
> <ClCompile Include="..\..\..\source\ocsd_error.cpp" />
> <ClCompile Include="..\..\..\source\ocsd_error_logger.cpp" />
> diff --git a/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj.filters b/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj.filters
> index 34a7737..c221d2f 100644
> --- a/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj.filters
> +++ b/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj.filters
> @@ -284,6 +284,9 @@
> <ClInclude Include="..\..\..\include\common\ocsd_pe_context.h">
> <Filter>Header Files\common</Filter>
> </ClInclude>
> + <ClInclude Include="..\..\..\include\common\ocsd_code_follower.h">
> + <Filter>Header Files\common</Filter>
> + </ClInclude>
> </ItemGroup>
> <ItemGroup>
> <ClCompile Include="..\..\..\source\trc_component.cpp">
> @@ -388,5 +391,8 @@
> <ClCompile Include="..\..\..\source\ocsd_version.cpp">
> <Filter>Source Files</Filter>
> </ClCompile>
> + <ClCompile Include="..\..\..\source\ocsd_code_follower.cpp">
> + <Filter>Source Files</Filter>
> + </ClCompile>
> </ItemGroup>
> </Project>
> \ No newline at end of file
> diff --git a/decoder/include/common/ocsd_code_follower.h b/decoder/include/common/ocsd_code_follower.h
> new file mode 100644
> index 0000000..f05ad5b
> --- /dev/null
> +++ b/decoder/include/common/ocsd_code_follower.h
> @@ -0,0 +1,225 @@
> +/*
> + * \file ocsd_code_follower.h
> + * \brief OpenCSD : Code follower for instruction trace decode
> + *
> + * \copyright Copyright (c) 2016, 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_OCSD_CODE_FOLLOWER_H_INCLUDED
> +#define ARM_OCSD_CODE_FOLLOWER_H_INCLUDED
> +
> +#include "ocsd_if_types.h"
> +#include "trc_pkt_types.h"
> +#include "comp_attach_pt_t.h"
> +#include "interfaces/trc_tgt_mem_access_i.h"
> +#include "interfaces/trc_instr_decode_i.h"
> +
> +/*!
> + * @class OcsdCodeFollower
> + * @brief The code follower looks for waypoints or addresses.
> + *
> + * Code follower used to determine the trace ranges for Atom or other waypoint
> + * elements. Uses memory accessor and I decoder to follow the code path.
> + *
> + */
> +class OcsdCodeFollower
> +{
> +public:
> + OcsdCodeFollower();
> + ~OcsdCodeFollower();
> +
> +//*********** setup API
> + void initInterfaces(componentAttachPt<ITargetMemAccess> *pMemAccess, componentAttachPt<IInstrDecode> *pIDecode);
> +
> +// set information for decode operation - static or occasionally changing settings
> +// per decode values are passed as parameters into the decode API calls.
> + void setCoreProfile(const ocsd_arch_profile_t profile); //!< core profile
> + void setMemSpaceAccess(const ocsd_mem_space_acc_t mem_acc_rule); //!< memory space to use for access (filtered by S/NS, EL etc).
> + void setMemSpaceCSID(const uint8_t csid); //!< memory spaces might be partitioned by CSID
> + void setISA(const ocsd_isa isa); //!< set the ISA for the decode.
> + void setDSBDMBasWP(); //!< DSB and DMB can be treated as WP in some archs.
> +
> +//********** code following API
> +
> + // standard WP search - for program flow trace
> + //ocsd_err_t followToAtomWP(idec_res_t &op_result, const ocsd_vaddr_t addrStart, const ocsd_atm_val A);
> +
> + // PTM exception code may require follow to an address
> + //ocsd_err_t followToAddress(idec_res_t &op_result, const ocsd_vaddr_t addrStart, const ocsd_atm_val A, const ocsd_vaddr_t addrMatch);
> +
> + // single instruction atom format such as ETMv3
> + ocsd_err_t followSingleAtom(const ocsd_vaddr_t addrStart, const ocsd_atm_val A);
> +
> + // follow N instructions
> + // ocsd_err_t followNInstructions(idec_res_t &op_result) // ETMv4 Q elements
> +
> +//*********************** results API
> + const ocsd_vaddr_t getRangeSt() const; //!< inclusive start address of decoded range (value passed in)
> + const ocsd_vaddr_t getRangeEn() const; //!< exclusive end address of decoded range (first instruction _not_ executed / potential next instruction).
> +
> + const bool hasNextAddr() const; //!< we have calulated the next address - otherwise this is needed from trace packets.
> + const ocsd_vaddr_t getNextAddr() const; //!< next address - valid if hasNextAddr() true.
> +
> + // information on last instruction executed in range.
> + const ocsd_instr_type getInstrType() const; //!< last instruction type
> + const ocsd_instr_subtype getInstrSubType() const; //!< last instruction sub-type
> + const bool isCondInstr() const; //!< is a conditional instruction
> + const bool isLink() const; //!< is a link (branch with link etc)
> + const bool ISAChanged() const; //!< next ISA different from input ISA.
> + const ocsd_isa nextISA() const; //!< ISA for next instruction
> +
> + // information on error conditions
> + const bool isNacc() const; //!< true if Memory Not Accessible (nacc) error occurred
> + void clearNacc(); //!< clear the nacc error flag
> + const ocsd_vaddr_t getNaccAddr() const; //!< get the nacc error address.
> +
> +private:
> + bool initFollowerState(); //!< clear all the o/p data and flags, check init valid.
> +
> + ocsd_err_t decodeSingleOpCode(); //!< decode single opcode address from current m_inst_info packet
> +
> + ocsd_instr_info m_instr_info;
> +
> + ocsd_vaddr_t m_st_range_addr; //!< start of excuted range - inclusive address.
> + ocsd_vaddr_t m_en_range_addr; //!< end of executed range - exclusive address.
> + ocsd_vaddr_t m_next_addr; //!< calcuated next address (could be eo range of branch address, not set for indirect branches)
> + bool m_b_next_valid; //!< true if next address valid, false if need address from trace packets.
> +
> + //! memory space rule to use when accessing memory.
> + ocsd_mem_space_acc_t m_mem_acc_rule;
> + //! memory space csid to use when accessing memory.
> + uint8_t m_mem_space_csid;
> +
> + ocsd_vaddr_t m_nacc_address; //!< memory address that was inaccessible - failed read @ start, or during follow operation
> + bool m_b_nacc_err; //!< memory NACC error - required address was unavailable.
> +
> + //! pointers to the memory access and i decode interfaces.
> + componentAttachPt<ITargetMemAccess> *m_pMemAccess;
> + componentAttachPt<IInstrDecode> *m_pIDecode;
> +
> +};
> +
> +#endif // ARM_OCSD_CODE_FOLLOWER_H_INCLUDED
> +
> +//*********** setup API
> +inline void OcsdCodeFollower::setCoreProfile(const ocsd_arch_profile_t profile)
> +{
> + m_instr_info.pe_type = profile;
> +}
> +
> +inline void OcsdCodeFollower::setMemSpaceAccess(const ocsd_mem_space_acc_t mem_acc_rule)
> +{
> + m_mem_acc_rule = mem_acc_rule;
> +}
> +
> +inline void OcsdCodeFollower::setMemSpaceCSID(const uint8_t csid)
> +{
> + m_mem_space_csid = csid;
> +}
> +
> +inline void OcsdCodeFollower::setISA(const ocsd_isa isa)
> +{
> + m_instr_info.isa = isa;
> +}
> +
> +inline void OcsdCodeFollower::setDSBDMBasWP()
> +{
> + m_instr_info.dsb_dmb_waypoints = 1;
> +}
> +
> +//**************************************** results API
> +inline const ocsd_vaddr_t OcsdCodeFollower::getRangeSt() const
> +{
> + return m_st_range_addr;
> +}
> +
> +inline const ocsd_vaddr_t OcsdCodeFollower::getRangeEn() const
> +{
> + return m_en_range_addr;
> +}
> +
> +inline const bool OcsdCodeFollower::hasNextAddr() const
> +{
> + return m_b_next_valid;
> +}
> +
> +inline const ocsd_vaddr_t OcsdCodeFollower::getNextAddr() const
> +{
> + return m_next_addr;
> +}
> +
> +// information on last instruction executed in range.
> +inline const ocsd_instr_type OcsdCodeFollower::getInstrType() const
> +{
> + return m_instr_info.type;
> +}
> +
> +inline const ocsd_instr_subtype OcsdCodeFollower::getInstrSubType() const
> +{
> + return m_instr_info.sub_type;
> +}
> +
> +inline const bool OcsdCodeFollower::isCondInstr() const
> +{
> + return (bool)(m_instr_info.is_conditional == 1);
> +}
> +
> +inline const bool OcsdCodeFollower::isLink() const
> +{
> + return (bool)(m_instr_info.is_link == 1);
> +}
> +
> +inline const bool OcsdCodeFollower::ISAChanged() const
> +{
> + return (bool)(m_instr_info.isa != m_instr_info.next_isa);
> +}
> +
> +inline const ocsd_isa OcsdCodeFollower::nextISA() const
> +{
> + return m_instr_info.next_isa;
> +}
> +
> +// information on error conditions
> +inline const bool OcsdCodeFollower::isNacc() const
> +{
> + return m_b_nacc_err;
> +}
> +
> +inline void OcsdCodeFollower::clearNacc()
> +{
> + m_b_nacc_err = false;
> +}
> +
> +inline const ocsd_vaddr_t OcsdCodeFollower::getNaccAddr() const
> +{
> + return m_nacc_address;
> +}
> +
> +/* End of File ocsd_code_follower.h */
> diff --git a/decoder/include/common/ocsd_pe_context.h b/decoder/include/common/ocsd_pe_context.h
> index 37764d9..fe06e90 100644
> --- a/decoder/include/common/ocsd_pe_context.h
> +++ b/decoder/include/common/ocsd_pe_context.h
> @@ -51,7 +51,7 @@ public:
> void resetCtxt();
>
> void setSecLevel(const ocsd_sec_level sl) { m_context.security_level = sl; };
> - void setEL(const ocsd_ex_level el) { m_context.exception_level = el; m_context.el_valid = 1; };
> + void setEL(const ocsd_ex_level el) { m_context.exception_level = el; m_context.el_valid = el > ocsd_EL_unknown ? 1 : 0; };
> void setCtxtID(const uint32_t id) { m_context.context_id = id; m_context.ctxt_id_valid = 1; };
> void setVMID(const uint32_t id) { m_context.vmid = id; m_context.vmid_valid = 1; };
> void set64bit(const bool is64bit) { m_context.bits64 = is64bit ? 1 : 0; };
> @@ -83,7 +83,7 @@ inline void OcsdPeContext::resetCtxt()
> m_context.context_id = 0;
> m_context.ctxt_id_valid = 0;
> m_context.el_valid = 0;
> - m_context.exception_level = ocsd_EL0;
> + m_context.exception_level = ocsd_EL_unknown;
> m_context.security_level = ocsd_sec_secure;
> m_context.vmid = 0;
> m_context.vmid_valid = 0;
> diff --git a/decoder/include/ocsd_if_types.h b/decoder/include/ocsd_if_types.h
> index 3fa3032..9e4b051 100644
> --- a/decoder/include/ocsd_if_types.h
> +++ b/decoder/include/ocsd_if_types.h
> @@ -110,6 +110,7 @@ typedef enum _ocsd_err_t {
> OCSD_ERR_UNSUPP_DECODE_PKT, /**< Packet not supported in decoder */
> OCSD_ERR_BAD_DECODE_PKT, /**< reserved or unknown packet in decoder. */
> OCSD_ERR_COMMIT_PKT_OVERRUN, /**< overrun in commit packet stack - tried to commit more than available */
> + OCSD_ERR_MEM_NACC, /**< unable to access required memory address */
> /* decode tree errors */
> OCSD_ERR_DCDT_NO_FORMATTER, /**< No formatter in use - operation not valid. */
> /* target memory access errors */
> @@ -330,6 +331,7 @@ typedef enum _ocsd_sec_level
> */
> typedef enum _ocsd_ex_level
> {
> + ocsd_EL_unknown = -1, /**< EL unknown / unsupported in trace */
if (!initFollowerState)
> ocsd_EL0 = 0, /**< EL0 */
> ocsd_EL1, /**< EL1 */
> ocsd_EL2, /**< EL2 */
> diff --git a/decoder/source/ocsd_code_follower.cpp b/decoder/source/ocsd_code_follower.cpp
> new file mode 100644
> index 0000000..b52704e
> --- /dev/null
> +++ b/decoder/source/ocsd_code_follower.cpp
> @@ -0,0 +1,155 @@
> +/*
> + * \file ocsd_code_follower.cpp
> + * \brief OpenCSD : Instruction Code path follower.
> + *
> + * \copyright Copyright (c) 2016, 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 "common/ocsd_code_follower.h"
> +
> +OcsdCodeFollower::OcsdCodeFollower()
> +{
> + m_instr_info.pe_type.arch = ARCH_UNKNOWN;
> + m_instr_info.pe_type.profile = profile_Unknown;
> + m_instr_info.isa = ocsd_isa_unknown;
> + m_instr_info.dsb_dmb_waypoints = 0;
> + m_instr_info.instr_addr = 0;
> + m_instr_info.opcode = 0;
> + m_pMemAccess = 0;
> + m_pIDecode = 0;
> + m_mem_space_csid = 0;
> + m_st_range_addr = m_en_range_addr = m_next_addr = 0;
> + m_b_next_valid = false;
> + m_b_nacc_err = false;
> +}
> +
> +OcsdCodeFollower::~OcsdCodeFollower()
> +{
> +}
> +
> +void OcsdCodeFollower::initInterfaces(componentAttachPt<ITargetMemAccess> *pMemAccess, componentAttachPt<IInstrDecode> *pIDecode)
> +{
> + m_pMemAccess = pMemAccess;
> + m_pIDecode = pIDecode;
> +}
> +
> +bool OcsdCodeFollower::initFollowerState()
> +{
> + bool initDone = false;
> +
> + // reset per follow flags
> + m_b_next_valid = false;
> + m_b_nacc_err = false;
> +
> + // set range addresses
> + m_en_range_addr = m_next_addr = m_st_range_addr;
> +
> +// check initialisation is valid.
> +
> + // must have attached memory access and i-decode objects
> + if(m_pMemAccess && m_pIDecode)
> + {
> + initDone = (m_pMemAccess->hasAttachedAndEnabled() && m_pIDecode->hasAttachedAndEnabled());
> + }
> + return initDone;
> +}
> +
> +/*!
> + * Decodes an instruction at a single location, calculates the next address
> + * if possible according to the instruction type and atom.
> + *
> + * @param addrStart : Address of the instruction
> + * @param A : Atom value - E or N
> + *
> + * @return ocsd_err_t : OCSD_OK - decode correct, check flags for next address
> + * : OCSD_ERR_MEM_NACC - unable to access memory area @ address - need new address in trace packet stream.
> + * : OCSD_ERR_NOT_INIT - not initialised - fatal.
> + * : OCSD_<other> - other error occured - fatal.
> + */
> +ocsd_err_t OcsdCodeFollower::followSingleAtom(const ocsd_vaddr_t addrStart, const ocsd_atm_val A)
> +{
> + ocsd_err_t err = OCSD_ERR_NOT_INIT;
> + if(initFollowerState())
return err;
> + {
> + m_st_range_addr = m_instr_info.instr_addr = addrStart;
> + err = decodeSingleOpCode();
> + if(err == OCSD_OK)
if (err != OCSD_OK)
return err;
That way you avoid the imbrication.
This initialisation isn't necessary.
> + {
> + // set end range - always after the instruction executed.
> + m_en_range_addr = m_instr_info.instr_addr + m_instr_info.instr_size;
> +
> + // assume next addr is the instruction after
> + m_next_addr = m_en_range_addr;
> + m_b_next_valid = true;
> +
> + // case when next address is different
> + switch(m_instr_info.type)
> + {
> + case OCSD_INSTR_BR:
> + if(A == ATOM_E) // executed the direct branch
> + m_next_addr = m_instr_info.branch_addr;
> + break;
> +
> + case OCSD_INSTR_BR_INDIRECT:
> + if(A == ATOM_E) // executed indirect branch
> + m_b_next_valid = false;
> + break;
> + }
> + }
> + }
> + return err;
> +}
> +
> +
> +ocsd_err_t OcsdCodeFollower::decodeSingleOpCode()
> +{
> + ocsd_err_t err = OCSD_OK;
> + uint32_t bytesReq = 4;
> + uint32_t opcode;
> + err = m_pMemAccess->first()->ReadTargetMemory(m_instr_info.instr_addr,m_mem_space_csid,m_mem_acc_rule,&bytesReq,(uint8_t *)&opcode);
> + if(err == OCSD_OK)
> + {
> + if(bytesReq == 4) // got memory.
Please explain the hard coded value.
> + {
> + m_instr_info.opcode = opcode;
> + err = m_pIDecode->first()->DecodeInstruction(&m_instr_info);
> + }
> + else // memory unavailable.
> + {
> + m_b_nacc_err = true;
> + m_nacc_address = m_instr_info.instr_addr;
> + err = OCSD_ERR_MEM_NACC;
> + }
> + }
> + return err;
> +}
> +
> +/* End of File ocsd_code_follower.cpp */
> --
> 1.9.1
>
> _______________________________________________
> CoreSight mailing list
> CoreSight@lists.linaro.org
> https://lists.linaro.org/mailman/listinfo/coresight