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 
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 
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 
67 TrcMemAccMapper::~TrcMemAccMapper()
68 {
69 }
70 
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
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 
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 
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 
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 
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 
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 /************************************************************************************/
182 TrcMemAccMapGlobalSpace::TrcMemAccMapGlobalSpace() : TrcMemAccMapper()
183 {
184 }
185 
186 TrcMemAccMapGlobalSpace::~TrcMemAccMapGlobalSpace()
187 {
188 }
189 
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 
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 
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 
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 
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 
267 void TrcMemAccMapGlobalSpace::clearAccessorList()
268 {
269     m_acc_global.clear();
270 }
271 
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 
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