1 /*
2 * \file trc_mem_acc_mapper.cpp
3 * \brief OpenCSD :
4 *
5 * \copyright Copyright (c) 2015, 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 #include "mem_acc/trc_mem_acc_mapper.h"
36 #include "mem_acc/trc_mem_acc_file.h"
37 #include "common/ocsd_error.h"
38
39 /************************************************************************************/
40 /* mappers base class */
41 /************************************************************************************/
42
43 #define USING_MEM_ACC_CACHE
44
TrcMemAccMapper()45 TrcMemAccMapper::TrcMemAccMapper() :
46 m_acc_curr(0),
47 m_trace_id_curr(0),
48 m_using_trace_id(false),
49 m_err_log(0)
50 {
51 #ifdef USING_MEM_ACC_CACHE
52 m_cache.enableCaching(true);
53 #endif
54 }
55
TrcMemAccMapper(bool using_trace_id)56 TrcMemAccMapper::TrcMemAccMapper(bool using_trace_id) :
57 m_acc_curr(0),
58 m_trace_id_curr(0),
59 m_using_trace_id(using_trace_id),
60 m_err_log(0)
61 {
62 #ifdef USING_MEM_ACC_CACHE
63 m_cache.enableCaching(true);
64 #endif
65 }
66
~TrcMemAccMapper()67 TrcMemAccMapper::~TrcMemAccMapper()
68 {
69 }
70
setErrorLog(ITraceErrorLog * err_log_i)71 void TrcMemAccMapper::setErrorLog(ITraceErrorLog *err_log_i)
72 {
73 m_err_log = err_log_i;
74 m_cache.setErrorLog(err_log_i);
75 }
76
77 // memory access interface
ReadTargetMemory(const ocsd_vaddr_t address,const uint8_t cs_trace_id,const ocsd_mem_space_acc_t mem_space,uint32_t * num_bytes,uint8_t * p_buffer)78 ocsd_err_t TrcMemAccMapper::ReadTargetMemory(const ocsd_vaddr_t address, const uint8_t cs_trace_id, const ocsd_mem_space_acc_t mem_space, uint32_t *num_bytes, uint8_t *p_buffer)
79 {
80 bool bReadFromCurr = true;
81 uint32_t readBytes = 0;
82 ocsd_err_t err = OCSD_OK;
83
84 /* see if the address is in any range we know */
85 if (!readFromCurrent(address, mem_space, cs_trace_id))
86 {
87 bReadFromCurr = findAccessor(address, mem_space, cs_trace_id);
88
89 // found a new accessor - invalidate any cache entries used by the previous one.
90 if (m_cache.enabled() && bReadFromCurr)
91 m_cache.invalidateAll();
92 }
93
94 /* if bReadFromCurr then we know m_acc_curr is set */
95 if (bReadFromCurr)
96 {
97 // use cache if enabled and the amount fits into a cache page
98 if (m_cache.enabled_for_size(*num_bytes))
99 {
100 // read from cache - or load a new cache page and read....
101 readBytes = *num_bytes;
102 err = m_cache.readBytesFromCache(m_acc_curr, address, mem_space, cs_trace_id, &readBytes, p_buffer);
103 if (err != OCSD_OK)
104 LogWarn(err, "Mem Acc: Cache access error");
105 }
106 else
107 {
108 readBytes = m_acc_curr->readBytes(address, mem_space, cs_trace_id, *num_bytes, p_buffer);
109 // guard against bad accessor returns (e.g. callback not obeying the rules for return values)
110 if (readBytes > *num_bytes)
111 {
112 err = OCSD_ERR_MEM_ACC_BAD_LEN;
113 LogWarn(err,"Mem acc: bad return length");
114 }
115 }
116 }
117
118 *num_bytes = readBytes;
119 return err;
120 }
121
InvalidateMemAccCache(const uint8_t)122 void TrcMemAccMapper::InvalidateMemAccCache(const uint8_t /* cs_trace_id */)
123 {
124 // default mapper does not use cs_trace_id for cache invalidation.
125 if (m_cache.enabled())
126 m_cache.invalidateAll();
127 m_acc_curr = 0;
128 }
129
RemoveAllAccessors()130 void TrcMemAccMapper::RemoveAllAccessors()
131 {
132 TrcMemAccessorBase *pAcc = 0;
133 pAcc = getFirstAccessor();
134 while(pAcc != 0)
135 {
136 TrcMemAccFactory::DestroyAccessor(pAcc);
137 pAcc = getNextAccessor();
138 if (m_cache.enabled())
139 m_cache.invalidateAll();
140 }
141 clearAccessorList();
142 if (m_cache.enabled())
143 m_cache.logAndClearCounts();
144 }
145
RemoveAccessorByAddress(const ocsd_vaddr_t st_address,const ocsd_mem_space_acc_t mem_space,const uint8_t cs_trace_id)146 ocsd_err_t TrcMemAccMapper::RemoveAccessorByAddress(const ocsd_vaddr_t st_address, const ocsd_mem_space_acc_t mem_space, const uint8_t cs_trace_id /* = 0 */)
147 {
148 ocsd_err_t err = OCSD_OK;
149 if(findAccessor(st_address,mem_space,cs_trace_id))
150 {
151 err = RemoveAccessor(m_acc_curr);
152 m_acc_curr = 0;
153 if (m_cache.enabled())
154 m_cache.invalidateAll();
155 }
156 else
157 err = OCSD_ERR_INVALID_PARAM_VAL;
158 if (m_cache.enabled())
159 m_cache.logAndClearCounts();
160 return err;
161 }
162
LogMessage(const std::string & msg)163 void TrcMemAccMapper::LogMessage(const std::string &msg)
164 {
165 if(m_err_log)
166 m_err_log->LogMessage(ITraceErrorLog::HANDLE_GEN_INFO,OCSD_ERR_SEV_INFO,msg);
167 }
168
LogWarn(const ocsd_err_t err,const std::string & msg)169 void TrcMemAccMapper::LogWarn(const ocsd_err_t err, const std::string &msg)
170 {
171 if (m_err_log)
172 {
173 ocsdError err_ocsd(OCSD_ERR_SEV_WARN,err,msg);
174 m_err_log->LogError(ITraceErrorLog::HANDLE_GEN_INFO, &err_ocsd);
175 }
176 }
177
178
179 /************************************************************************************/
180 /* mappers global address space class - no differentiation in core trace IDs */
181 /************************************************************************************/
TrcMemAccMapGlobalSpace()182 TrcMemAccMapGlobalSpace::TrcMemAccMapGlobalSpace() : TrcMemAccMapper()
183 {
184 }
185
~TrcMemAccMapGlobalSpace()186 TrcMemAccMapGlobalSpace::~TrcMemAccMapGlobalSpace()
187 {
188 }
189
AddAccessor(TrcMemAccessorBase * p_accessor,const uint8_t)190 ocsd_err_t TrcMemAccMapGlobalSpace::AddAccessor(TrcMemAccessorBase *p_accessor, const uint8_t /*cs_trace_id*/)
191 {
192 ocsd_err_t err = OCSD_OK;
193 bool bOverLap = false;
194
195 if(!p_accessor->validateRange())
196 return OCSD_ERR_MEM_ACC_RANGE_INVALID;
197
198 std::vector<TrcMemAccessorBase *>::const_iterator it = m_acc_global.begin();
199 while((it != m_acc_global.end()) && !bOverLap)
200 {
201 // if overlap and memory space match
202 if( ((*it)->overLapRange(p_accessor)) &&
203 ((*it)->inMemSpace(p_accessor->getMemSpace()))
204 )
205 {
206 bOverLap = true;
207 err = OCSD_ERR_MEM_ACC_OVERLAP;
208 }
209 it++;
210 }
211
212 // no overlap - add to the list of ranges.
213 if(!bOverLap)
214 m_acc_global.push_back(p_accessor);
215
216 return err;
217 }
218
findAccessor(const ocsd_vaddr_t address,const ocsd_mem_space_acc_t mem_space,const uint8_t)219 bool TrcMemAccMapGlobalSpace::findAccessor(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t /*cs_trace_id*/)
220 {
221 bool bFound = false;
222 std::vector<TrcMemAccessorBase *>::const_iterator it = m_acc_global.begin();
223 while((it != m_acc_global.end()) && !bFound)
224 {
225 if( (*it)->addrInRange(address) &&
226 (*it)->inMemSpace(mem_space))
227 {
228 bFound = true;
229 m_acc_curr = *it;
230 }
231 it++;
232 }
233 return bFound;
234 }
235
readFromCurrent(const ocsd_vaddr_t address,const ocsd_mem_space_acc_t mem_space,const uint8_t)236 bool TrcMemAccMapGlobalSpace::readFromCurrent(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t /*cs_trace_id*/)
237 {
238 bool readFromCurr = false;
239 if(m_acc_curr)
240 readFromCurr = (m_acc_curr->addrInRange(address) && m_acc_curr->inMemSpace(mem_space));
241 return readFromCurr;
242 }
243
244
getFirstAccessor()245 TrcMemAccessorBase * TrcMemAccMapGlobalSpace::getFirstAccessor()
246 {
247 TrcMemAccessorBase *p_acc = 0;
248 m_acc_it = m_acc_global.begin();
249 if(m_acc_it != m_acc_global.end())
250 {
251 p_acc = *m_acc_it;
252 }
253 return p_acc;
254 }
255
getNextAccessor()256 TrcMemAccessorBase *TrcMemAccMapGlobalSpace::getNextAccessor()
257 {
258 TrcMemAccessorBase *p_acc = 0;
259 m_acc_it++;
260 if(m_acc_it != m_acc_global.end())
261 {
262 p_acc = *m_acc_it;
263 }
264 return p_acc;
265 }
266
clearAccessorList()267 void TrcMemAccMapGlobalSpace::clearAccessorList()
268 {
269 m_acc_global.clear();
270 }
271
RemoveAccessor(const TrcMemAccessorBase * p_accessor)272 ocsd_err_t TrcMemAccMapGlobalSpace::RemoveAccessor(const TrcMemAccessorBase *p_accessor)
273 {
274 bool bFound = false;
275 TrcMemAccessorBase *p_acc = getFirstAccessor();
276 while(p_acc != 0)
277 {
278 if(p_acc == p_accessor)
279 {
280 m_acc_global.erase(m_acc_it);
281 TrcMemAccFactory::DestroyAccessor(p_acc);
282 p_acc = 0;
283 bFound = true;
284 }
285 else
286 p_acc = getNextAccessor();
287 }
288 return bFound ? OCSD_OK : OCSD_ERR_INVALID_PARAM_VAL;
289 }
290
291
logMappedRanges()292 void TrcMemAccMapGlobalSpace::logMappedRanges()
293 {
294 std::string accStr;
295 TrcMemAccessorBase *pAccessor = getFirstAccessor();
296 LogMessage("Mapped Memory Accessors\n");
297 while(pAccessor != 0)
298 {
299 pAccessor->getMemAccString(accStr);
300 accStr += "\n";
301 LogMessage(accStr);
302 pAccessor = getNextAccessor();
303 }
304 LogMessage("========================\n");
305 }
306
307 /* End of File trc_mem_acc_mapper.cpp */
308