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 
105 private:
106     bool initFollowerState();       //!< clear all the o/p data and flags, check init valid.
107 
108     ocsd_err_t decodeSingleOpCode();      //!< decode single opcode address from current m_inst_info packet
109 
110     ocsd_instr_info m_instr_info;
111 
112     ocsd_vaddr_t m_st_range_addr;   //!< start of excuted range - inclusive address.
113     ocsd_vaddr_t m_en_range_addr;   //!< end of executed range - exclusive address.
114     ocsd_vaddr_t m_next_addr;       //!< calcuated next address (could be eo range of branch address, not set for indirect branches)
115     bool m_b_next_valid;            //!< true if next address valid, false if need address from trace packets.
116 
117     //! memory space rule to use when accessing memory.
118     ocsd_mem_space_acc_t m_mem_acc_rule;
119     //! memory space csid to use when accessing memory.
120     uint8_t              m_mem_space_csid;
121 
122     ocsd_vaddr_t m_nacc_address;    //!< memory address that was inaccessible - failed read @ start, or during follow operation
123     bool m_b_nacc_err;              //!< memory NACC error - required address was unavailable.
124 
125     //! pointers to the memory access and i decode interfaces.
126     componentAttachPt<ITargetMemAccess> *m_pMemAccess;
127     componentAttachPt<IInstrDecode> *m_pIDecode;
128 
129 };
130 
131 #endif // ARM_OCSD_CODE_FOLLOWER_H_INCLUDED
132 
133 //*********** setup API
134 inline void OcsdCodeFollower::setArchProfile(const ocsd_arch_profile_t profile)
135 {
136     m_instr_info.pe_type = profile;
137 }
138 
139 inline void OcsdCodeFollower::setMemSpaceAccess(const ocsd_mem_space_acc_t mem_acc_rule)
140 {
141     m_mem_acc_rule = mem_acc_rule;
142 }
143 
144 inline void  OcsdCodeFollower::setMemSpaceCSID(const uint8_t csid)
145 {
146     m_mem_space_csid = csid;
147 }
148 
149 inline void OcsdCodeFollower::setISA(const ocsd_isa isa)
150 {
151     m_instr_info.isa = isa;
152 }
153 
154 inline void OcsdCodeFollower::setDSBDMBasWP()
155 {
156     m_instr_info.dsb_dmb_waypoints = 1;
157 }
158 
159 //**************************************** results API
160 inline const ocsd_vaddr_t OcsdCodeFollower::getRangeSt() const
161 {
162     return m_st_range_addr;
163 }
164 
165 inline const ocsd_vaddr_t OcsdCodeFollower::getRangeEn() const
166 {
167     return m_en_range_addr;
168 }
169 
170 inline const bool OcsdCodeFollower::hasRange() const
171 {
172     return m_st_range_addr < m_en_range_addr;
173 }
174 
175 inline const bool OcsdCodeFollower::hasNextAddr() const
176 {
177     return m_b_next_valid;
178 }
179 
180 inline const ocsd_vaddr_t OcsdCodeFollower::getNextAddr() const
181 {
182     return m_next_addr;
183 }
184 
185 // information on last instruction executed in range.
186 inline const ocsd_instr_type OcsdCodeFollower::getInstrType() const
187 {
188     return m_instr_info.type;
189 }
190 
191 inline const ocsd_instr_subtype OcsdCodeFollower::getInstrSubType() const
192 {
193     return m_instr_info.sub_type;
194 }
195 
196 inline const uint8_t  OcsdCodeFollower::getInstrSize() const
197 {
198     return m_instr_info.instr_size;
199 }
200 
201 inline const bool OcsdCodeFollower::isCondInstr() const
202 {
203     return (bool)(m_instr_info.is_conditional == 1);
204 }
205 
206 inline const bool OcsdCodeFollower::isLink() const
207 {
208     return (bool)(m_instr_info.is_link == 1);
209 }
210 
211 inline const bool OcsdCodeFollower::ISAChanged() const
212 {
213     return (bool)(m_instr_info.isa != m_instr_info.next_isa);
214 }
215 
216 inline const ocsd_isa OcsdCodeFollower::nextISA() const
217 {
218     return m_instr_info.next_isa;
219 }
220 
221 // information on error conditions
222 inline const bool OcsdCodeFollower::isNacc() const
223 {
224     return m_b_nacc_err;
225 }
226 
227 inline void OcsdCodeFollower::clearNacc()
228 {
229     m_b_nacc_err = false;
230 }
231 
232 inline const ocsd_vaddr_t OcsdCodeFollower::getNaccAddr() const
233 {
234     return m_nacc_address;
235 }
236 
237 /* End of File ocsd_code_follower.h */
238