1 /*
2 * \file ocsd_code_follower.h
3 * \brief OpenCSD : Code follower for instruction trace decode
4 *
5 * \copyright Copyright (c) 2016, ARM Limited. All Rights Reserved.
6 */
7
8 /*
9 * Redistribution and use in source and binary forms, with or without modification,
10 * are permitted provided that the following conditions are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 *
19 * 3. Neither the name of the copyright holder nor the names of its contributors
20 * may be used to endorse or promote products derived from this software without
21 * specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #ifndef ARM_OCSD_CODE_FOLLOWER_H_INCLUDED
36 #define ARM_OCSD_CODE_FOLLOWER_H_INCLUDED
37
38 #include "opencsd/ocsd_if_types.h"
39 #include "opencsd/trc_pkt_types.h"
40 #include "comp_attach_pt_t.h"
41 #include "interfaces/trc_tgt_mem_access_i.h"
42 #include "interfaces/trc_instr_decode_i.h"
43
44 /*!
45 * @class OcsdCodeFollower
46 * @brief The code follower looks for waypoints or addresses.
47 *
48 * Code follower used to determine the trace ranges for Atom or other waypoint
49 * elements. Uses memory accessor and I decoder to follow the code path.
50 *
51 */
52 class OcsdCodeFollower
53 {
54 public:
55 OcsdCodeFollower();
56 ~OcsdCodeFollower();
57
58 //*********** setup API
59 void initInterfaces(componentAttachPt<ITargetMemAccess> *pMemAccess, componentAttachPt<IInstrDecode> *pIDecode);
60
61 // set information for decode operation - static or occasionally changing settings
62 // per decode values are passed as parameters into the decode API calls.
63 void setArchProfile(const ocsd_arch_profile_t profile); //!< core profile
64 void setMemSpaceAccess(const ocsd_mem_space_acc_t mem_acc_rule); //!< memory space to use for access (filtered by S/NS, EL etc).
65 void setMemSpaceCSID(const uint8_t csid); //!< memory spaces might be partitioned by CSID
66 void setISA(const ocsd_isa isa); //!< set the ISA for the decode.
67 void setDSBDMBasWP(); //!< DSB and DMB can be treated as WP in some archs.
68
69 //********** code following API
70
71 // standard WP search - for program flow trace
72 //ocsd_err_t followToAtomWP(idec_res_t &op_result, const ocsd_vaddr_t addrStart, const ocsd_atm_val A);
73
74 // PTM exception code may require follow to an address
75 //ocsd_err_t followToAddress(idec_res_t &op_result, const ocsd_vaddr_t addrStart, const ocsd_atm_val A, const ocsd_vaddr_t addrMatch);
76
77 // single instruction atom format such as ETMv3
78 ocsd_err_t followSingleAtom(const ocsd_vaddr_t addrStart, const ocsd_atm_val A);
79
80 // follow N instructions
81 // ocsd_err_t followNInstructions(idec_res_t &op_result) // ETMv4 Q elements
82
83 //*********************** results API
84 const ocsd_vaddr_t getRangeSt() const; //!< inclusive start address of decoded range (value passed in)
85 const ocsd_vaddr_t getRangeEn() const; //!< exclusive end address of decoded range (first instruction _not_ executed / potential next instruction).
86 const bool hasRange() const; //!< we have a valid range executed (may be false if nacc).
87
88 const bool hasNextAddr() const; //!< we have calulated the next address - otherwise this is needed from trace packets.
89 const ocsd_vaddr_t getNextAddr() const; //!< next address - valid if hasNextAddr() true.
90
91 // information on last instruction executed in range.
92 const ocsd_instr_type getInstrType() const; //!< last instruction type
93 const ocsd_instr_subtype getInstrSubType() const; //!< last instruction sub-type
94 const bool isCondInstr() const; //!< is a conditional instruction
95 const bool isLink() const; //!< is a link (branch with link etc)
96 const bool ISAChanged() const; //!< next ISA different from input ISA.
97 const ocsd_isa nextISA() const; //!< ISA for next instruction
98 const uint8_t getInstrSize() const; //!< Get the last instruction size.
99
100 // information on error conditions
101 const bool isNacc() const; //!< true if Memory Not Accessible (nacc) error occurred
102 void clearNacc(); //!< clear the nacc error flag
103 const ocsd_vaddr_t getNaccAddr() const; //!< get the nacc error address.
104 const ocsd_mem_space_acc_t getMemSpaceAccess() const; //!< get the memory space used for access.
105
106 private:
107 bool initFollowerState(); //!< clear all the o/p data and flags, check init valid.
108
109 ocsd_err_t decodeSingleOpCode(); //!< decode single opcode address from current m_inst_info packet
110
111 ocsd_instr_info m_instr_info;
112
113 ocsd_vaddr_t m_st_range_addr; //!< start of excuted range - inclusive address.
114 ocsd_vaddr_t m_en_range_addr; //!< end of executed range - exclusive address.
115 ocsd_vaddr_t m_next_addr; //!< calcuated next address (could be eo range of branch address, not set for indirect branches)
116 bool m_b_next_valid; //!< true if next address valid, false if need address from trace packets.
117
118 //! memory space rule to use when accessing memory.
119 ocsd_mem_space_acc_t m_mem_acc_rule;
120 //! memory space csid to use when accessing memory.
121 uint8_t m_mem_space_csid;
122
123 ocsd_vaddr_t m_nacc_address; //!< memory address that was inaccessible - failed read @ start, or during follow operation
124 bool m_b_nacc_err; //!< memory NACC error - required address was unavailable.
125
126 //! pointers to the memory access and i decode interfaces.
127 componentAttachPt<ITargetMemAccess> *m_pMemAccess;
128 componentAttachPt<IInstrDecode> *m_pIDecode;
129
130 };
131
132 #endif // ARM_OCSD_CODE_FOLLOWER_H_INCLUDED
133
134 //*********** setup API
setArchProfile(const ocsd_arch_profile_t profile)135 inline void OcsdCodeFollower::setArchProfile(const ocsd_arch_profile_t profile)
136 {
137 m_instr_info.pe_type = profile;
138 }
139
setMemSpaceAccess(const ocsd_mem_space_acc_t mem_acc_rule)140 inline void OcsdCodeFollower::setMemSpaceAccess(const ocsd_mem_space_acc_t mem_acc_rule)
141 {
142 m_mem_acc_rule = mem_acc_rule;
143 }
144
getMemSpaceAccess()145 inline const ocsd_mem_space_acc_t OcsdCodeFollower::getMemSpaceAccess() const
146 {
147 return m_mem_acc_rule;
148 }
149
setMemSpaceCSID(const uint8_t csid)150 inline void OcsdCodeFollower::setMemSpaceCSID(const uint8_t csid)
151 {
152 m_mem_space_csid = csid;
153 }
154
setISA(const ocsd_isa isa)155 inline void OcsdCodeFollower::setISA(const ocsd_isa isa)
156 {
157 m_instr_info.isa = isa;
158 }
159
setDSBDMBasWP()160 inline void OcsdCodeFollower::setDSBDMBasWP()
161 {
162 m_instr_info.dsb_dmb_waypoints = 1;
163 }
164
165 //**************************************** results API
getRangeSt()166 inline const ocsd_vaddr_t OcsdCodeFollower::getRangeSt() const
167 {
168 return m_st_range_addr;
169 }
170
getRangeEn()171 inline const ocsd_vaddr_t OcsdCodeFollower::getRangeEn() const
172 {
173 return m_en_range_addr;
174 }
175
hasRange()176 inline const bool OcsdCodeFollower::hasRange() const
177 {
178 return m_st_range_addr < m_en_range_addr;
179 }
180
hasNextAddr()181 inline const bool OcsdCodeFollower::hasNextAddr() const
182 {
183 return m_b_next_valid;
184 }
185
getNextAddr()186 inline const ocsd_vaddr_t OcsdCodeFollower::getNextAddr() const
187 {
188 return m_next_addr;
189 }
190
191 // information on last instruction executed in range.
getInstrType()192 inline const ocsd_instr_type OcsdCodeFollower::getInstrType() const
193 {
194 return m_instr_info.type;
195 }
196
getInstrSubType()197 inline const ocsd_instr_subtype OcsdCodeFollower::getInstrSubType() const
198 {
199 return m_instr_info.sub_type;
200 }
201
getInstrSize()202 inline const uint8_t OcsdCodeFollower::getInstrSize() const
203 {
204 return m_instr_info.instr_size;
205 }
206
isCondInstr()207 inline const bool OcsdCodeFollower::isCondInstr() const
208 {
209 return (bool)(m_instr_info.is_conditional == 1);
210 }
211
isLink()212 inline const bool OcsdCodeFollower::isLink() const
213 {
214 return (bool)(m_instr_info.is_link == 1);
215 }
216
ISAChanged()217 inline const bool OcsdCodeFollower::ISAChanged() const
218 {
219 return (bool)(m_instr_info.isa != m_instr_info.next_isa);
220 }
221
nextISA()222 inline const ocsd_isa OcsdCodeFollower::nextISA() const
223 {
224 return m_instr_info.next_isa;
225 }
226
227 // information on error conditions
isNacc()228 inline const bool OcsdCodeFollower::isNacc() const
229 {
230 return m_b_nacc_err;
231 }
232
clearNacc()233 inline void OcsdCodeFollower::clearNacc()
234 {
235 m_b_nacc_err = false;
236 }
237
getNaccAddr()238 inline const ocsd_vaddr_t OcsdCodeFollower::getNaccAddr() const
239 {
240 return m_nacc_address;
241 }
242
243 /* End of File ocsd_code_follower.h */
244