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