xref: /freebsd-src/contrib/opencsd/decoder/source/mem_acc/trc_mem_acc_mapper.cpp (revision 46e6e290975f19ea62d03f90ac3e523af4dae557)
1c120c564SAndrew Turner /*
2c120c564SAndrew Turner  * \file       trc_mem_acc_mapper.cpp
3c120c564SAndrew Turner  * \brief      OpenCSD :
4c120c564SAndrew Turner  *
5c120c564SAndrew Turner  * \copyright  Copyright (c) 2015, ARM Limited. All Rights Reserved.
6c120c564SAndrew Turner  */
7c120c564SAndrew Turner 
8c120c564SAndrew Turner /*
9c120c564SAndrew Turner  * Redistribution and use in source and binary forms, with or without modification,
10c120c564SAndrew Turner  * are permitted provided that the following conditions are met:
11c120c564SAndrew Turner  *
12c120c564SAndrew Turner  * 1. Redistributions of source code must retain the above copyright notice,
13c120c564SAndrew Turner  * this list of conditions and the following disclaimer.
14c120c564SAndrew Turner  *
15c120c564SAndrew Turner  * 2. Redistributions in binary form must reproduce the above copyright notice,
16c120c564SAndrew Turner  * this list of conditions and the following disclaimer in the documentation
17c120c564SAndrew Turner  * and/or other materials provided with the distribution.
18c120c564SAndrew Turner  *
19c120c564SAndrew Turner  * 3. Neither the name of the copyright holder nor the names of its contributors
20c120c564SAndrew Turner  * may be used to endorse or promote products derived from this software without
21c120c564SAndrew Turner  * specific prior written permission.
22c120c564SAndrew Turner  *
23c120c564SAndrew Turner  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
24c120c564SAndrew Turner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25c120c564SAndrew Turner  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26c120c564SAndrew Turner  * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27c120c564SAndrew Turner  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28c120c564SAndrew Turner  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29c120c564SAndrew Turner  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30c120c564SAndrew Turner  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31c120c564SAndrew Turner  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32c120c564SAndrew Turner  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33c120c564SAndrew Turner  */
34c120c564SAndrew Turner 
35c120c564SAndrew Turner #include "mem_acc/trc_mem_acc_mapper.h"
36c120c564SAndrew Turner #include "mem_acc/trc_mem_acc_file.h"
37c120c564SAndrew Turner #include "common/ocsd_error.h"
38c120c564SAndrew Turner 
39c120c564SAndrew Turner /************************************************************************************/
40c120c564SAndrew Turner /* mappers base class */
41c120c564SAndrew Turner /************************************************************************************/
42c120c564SAndrew Turner 
43c120c564SAndrew Turner #define USING_MEM_ACC_CACHE
44c120c564SAndrew Turner 
TrcMemAccMapper()45c120c564SAndrew Turner TrcMemAccMapper::TrcMemAccMapper() :
46c120c564SAndrew Turner     m_acc_curr(0),
47c120c564SAndrew Turner     m_trace_id_curr(0),
48c120c564SAndrew Turner     m_using_trace_id(false),
49c120c564SAndrew Turner     m_err_log(0)
50c120c564SAndrew Turner {
51c120c564SAndrew Turner #ifdef USING_MEM_ACC_CACHE
52c120c564SAndrew Turner     m_cache.enableCaching(true);
53c120c564SAndrew Turner #endif
54c120c564SAndrew Turner }
55c120c564SAndrew Turner 
TrcMemAccMapper(bool using_trace_id)56c120c564SAndrew Turner TrcMemAccMapper::TrcMemAccMapper(bool using_trace_id) :
57c120c564SAndrew Turner     m_acc_curr(0),
58c120c564SAndrew Turner     m_trace_id_curr(0),
59c120c564SAndrew Turner     m_using_trace_id(using_trace_id),
60c120c564SAndrew Turner     m_err_log(0)
61c120c564SAndrew Turner {
62c120c564SAndrew Turner #ifdef USING_MEM_ACC_CACHE
63c120c564SAndrew Turner     m_cache.enableCaching(true);
64c120c564SAndrew Turner #endif
65c120c564SAndrew Turner }
66c120c564SAndrew Turner 
~TrcMemAccMapper()67c120c564SAndrew Turner TrcMemAccMapper::~TrcMemAccMapper()
68c120c564SAndrew Turner {
69c120c564SAndrew Turner }
70c120c564SAndrew Turner 
setErrorLog(ITraceErrorLog * err_log_i)71c120c564SAndrew Turner void TrcMemAccMapper::setErrorLog(ITraceErrorLog *err_log_i)
72c120c564SAndrew Turner {
73c120c564SAndrew Turner     m_err_log = err_log_i;
74c120c564SAndrew Turner     m_cache.setErrorLog(err_log_i);
75c120c564SAndrew Turner }
76c120c564SAndrew Turner 
77c120c564SAndrew Turner // 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)78c120c564SAndrew Turner 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)
79c120c564SAndrew Turner {
80c120c564SAndrew Turner     bool bReadFromCurr = true;
81c120c564SAndrew Turner     uint32_t readBytes = 0;
82c120c564SAndrew Turner     ocsd_err_t err = OCSD_OK;
83c120c564SAndrew Turner 
84c120c564SAndrew Turner     /* see if the address is in any range we know */
85c120c564SAndrew Turner     if (!readFromCurrent(address, mem_space, cs_trace_id))
86c120c564SAndrew Turner     {
87c120c564SAndrew Turner         bReadFromCurr = findAccessor(address, mem_space, cs_trace_id);
88c120c564SAndrew Turner 
89c120c564SAndrew Turner         // found a new accessor - invalidate any cache entries used by the previous one.
90c120c564SAndrew Turner         if (m_cache.enabled() && bReadFromCurr)
91c120c564SAndrew Turner             m_cache.invalidateAll();
92c120c564SAndrew Turner     }
93c120c564SAndrew Turner 
94c120c564SAndrew Turner     /* if bReadFromCurr then we know m_acc_curr is set */
95c120c564SAndrew Turner     if (bReadFromCurr)
96c120c564SAndrew Turner     {
97c120c564SAndrew Turner         // use cache if enabled and the amount fits into a cache page
98c120c564SAndrew Turner         if (m_cache.enabled_for_size(*num_bytes))
99c120c564SAndrew Turner         {
100c120c564SAndrew Turner             // read from cache - or load a new cache page and read....
101c120c564SAndrew Turner             readBytes = *num_bytes;
102c120c564SAndrew Turner             err = m_cache.readBytesFromCache(m_acc_curr, address, mem_space, cs_trace_id, &readBytes, p_buffer);
103c120c564SAndrew Turner             if (err != OCSD_OK)
104c120c564SAndrew Turner                 LogWarn(err, "Mem Acc: Cache access error");
105c120c564SAndrew Turner         }
106c120c564SAndrew Turner         else
107c120c564SAndrew Turner         {
108c120c564SAndrew Turner             readBytes = m_acc_curr->readBytes(address, mem_space, cs_trace_id, *num_bytes, p_buffer);
109c120c564SAndrew Turner             // guard against bad accessor returns (e.g. callback not obeying the rules for return values)
110c120c564SAndrew Turner             if (readBytes > *num_bytes)
111c120c564SAndrew Turner             {
112c120c564SAndrew Turner                 err = OCSD_ERR_MEM_ACC_BAD_LEN;
113c120c564SAndrew Turner                 LogWarn(err,"Mem acc: bad return length");
114c120c564SAndrew Turner             }
115c120c564SAndrew Turner         }
116c120c564SAndrew Turner     }
117c120c564SAndrew Turner 
118c120c564SAndrew Turner     *num_bytes = readBytes;
119c120c564SAndrew Turner     return err;
120c120c564SAndrew Turner }
121c120c564SAndrew Turner 
InvalidateMemAccCache(const uint8_t)122*46e6e290SRuslan Bukin void TrcMemAccMapper::InvalidateMemAccCache(const uint8_t /* cs_trace_id */)
123*46e6e290SRuslan Bukin {
124*46e6e290SRuslan Bukin     // default mapper does not use cs_trace_id for cache invalidation.
125*46e6e290SRuslan Bukin     if (m_cache.enabled())
126*46e6e290SRuslan Bukin         m_cache.invalidateAll();
127*46e6e290SRuslan Bukin     m_acc_curr = 0;
128*46e6e290SRuslan Bukin }
129*46e6e290SRuslan Bukin 
RemoveAllAccessors()130c120c564SAndrew Turner void TrcMemAccMapper::RemoveAllAccessors()
131c120c564SAndrew Turner {
132c120c564SAndrew Turner     TrcMemAccessorBase *pAcc = 0;
133c120c564SAndrew Turner     pAcc = getFirstAccessor();
134c120c564SAndrew Turner     while(pAcc != 0)
135c120c564SAndrew Turner     {
136c120c564SAndrew Turner         TrcMemAccFactory::DestroyAccessor(pAcc);
137c120c564SAndrew Turner         pAcc = getNextAccessor();
138c120c564SAndrew Turner         if (m_cache.enabled())
139c120c564SAndrew Turner             m_cache.invalidateAll();
140c120c564SAndrew Turner     }
141c120c564SAndrew Turner     clearAccessorList();
142c120c564SAndrew Turner     if (m_cache.enabled())
143c120c564SAndrew Turner         m_cache.logAndClearCounts();
144c120c564SAndrew Turner }
145c120c564SAndrew Turner 
RemoveAccessorByAddress(const ocsd_vaddr_t st_address,const ocsd_mem_space_acc_t mem_space,const uint8_t cs_trace_id)146c120c564SAndrew Turner 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 */)
147c120c564SAndrew Turner {
148c120c564SAndrew Turner     ocsd_err_t err = OCSD_OK;
149c120c564SAndrew Turner     if(findAccessor(st_address,mem_space,cs_trace_id))
150c120c564SAndrew Turner     {
151c120c564SAndrew Turner         err = RemoveAccessor(m_acc_curr);
152c120c564SAndrew Turner         m_acc_curr = 0;
153c120c564SAndrew Turner         if (m_cache.enabled())
154c120c564SAndrew Turner             m_cache.invalidateAll();
155c120c564SAndrew Turner     }
156c120c564SAndrew Turner     else
157c120c564SAndrew Turner         err = OCSD_ERR_INVALID_PARAM_VAL;
158c120c564SAndrew Turner     if (m_cache.enabled())
159c120c564SAndrew Turner         m_cache.logAndClearCounts();
160c120c564SAndrew Turner     return err;
161c120c564SAndrew Turner }
162c120c564SAndrew Turner 
LogMessage(const std::string & msg)163c120c564SAndrew Turner void  TrcMemAccMapper::LogMessage(const std::string &msg)
164c120c564SAndrew Turner {
165c120c564SAndrew Turner     if(m_err_log)
166c120c564SAndrew Turner         m_err_log->LogMessage(ITraceErrorLog::HANDLE_GEN_INFO,OCSD_ERR_SEV_INFO,msg);
167c120c564SAndrew Turner }
168c120c564SAndrew Turner 
LogWarn(const ocsd_err_t err,const std::string & msg)169c120c564SAndrew Turner void TrcMemAccMapper::LogWarn(const ocsd_err_t err, const std::string &msg)
170c120c564SAndrew Turner {
171c120c564SAndrew Turner     if (m_err_log)
172c120c564SAndrew Turner     {
173c120c564SAndrew Turner         ocsdError err_ocsd(OCSD_ERR_SEV_WARN,err,msg);
174c120c564SAndrew Turner         m_err_log->LogError(ITraceErrorLog::HANDLE_GEN_INFO, &err_ocsd);
175c120c564SAndrew Turner     }
176c120c564SAndrew Turner }
177c120c564SAndrew Turner 
178c120c564SAndrew Turner 
179c120c564SAndrew Turner /************************************************************************************/
180c120c564SAndrew Turner /* mappers global address space class - no differentiation in core trace IDs */
181c120c564SAndrew Turner /************************************************************************************/
TrcMemAccMapGlobalSpace()182c120c564SAndrew Turner TrcMemAccMapGlobalSpace::TrcMemAccMapGlobalSpace() : TrcMemAccMapper()
183c120c564SAndrew Turner {
184c120c564SAndrew Turner }
185c120c564SAndrew Turner 
~TrcMemAccMapGlobalSpace()186c120c564SAndrew Turner TrcMemAccMapGlobalSpace::~TrcMemAccMapGlobalSpace()
187c120c564SAndrew Turner {
188c120c564SAndrew Turner }
189c120c564SAndrew Turner 
AddAccessor(TrcMemAccessorBase * p_accessor,const uint8_t)190c120c564SAndrew Turner ocsd_err_t TrcMemAccMapGlobalSpace::AddAccessor(TrcMemAccessorBase *p_accessor, const uint8_t /*cs_trace_id*/)
191c120c564SAndrew Turner {
192c120c564SAndrew Turner     ocsd_err_t err = OCSD_OK;
193c120c564SAndrew Turner     bool bOverLap = false;
194c120c564SAndrew Turner 
195c120c564SAndrew Turner     if(!p_accessor->validateRange())
196c120c564SAndrew Turner         return OCSD_ERR_MEM_ACC_RANGE_INVALID;
197c120c564SAndrew Turner 
198c120c564SAndrew Turner     std::vector<TrcMemAccessorBase *>::const_iterator it =  m_acc_global.begin();
199c120c564SAndrew Turner     while((it != m_acc_global.end()) && !bOverLap)
200c120c564SAndrew Turner     {
201c120c564SAndrew Turner         // if overlap and memory space match
202c120c564SAndrew Turner         if( ((*it)->overLapRange(p_accessor)) &&
203c120c564SAndrew Turner             ((*it)->inMemSpace(p_accessor->getMemSpace()))
204c120c564SAndrew Turner             )
205c120c564SAndrew Turner         {
206c120c564SAndrew Turner             bOverLap = true;
207c120c564SAndrew Turner             err = OCSD_ERR_MEM_ACC_OVERLAP;
208c120c564SAndrew Turner         }
209c120c564SAndrew Turner         it++;
210c120c564SAndrew Turner     }
211c120c564SAndrew Turner 
212c120c564SAndrew Turner     // no overlap - add to the list of ranges.
213c120c564SAndrew Turner     if(!bOverLap)
214c120c564SAndrew Turner         m_acc_global.push_back(p_accessor);
215c120c564SAndrew Turner 
216c120c564SAndrew Turner     return err;
217c120c564SAndrew Turner }
218c120c564SAndrew Turner 
findAccessor(const ocsd_vaddr_t address,const ocsd_mem_space_acc_t mem_space,const uint8_t)219c120c564SAndrew Turner bool TrcMemAccMapGlobalSpace::findAccessor(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t /*cs_trace_id*/)
220c120c564SAndrew Turner {
221c120c564SAndrew Turner     bool bFound = false;
222c120c564SAndrew Turner     std::vector<TrcMemAccessorBase *>::const_iterator it =  m_acc_global.begin();
223c120c564SAndrew Turner     while((it != m_acc_global.end()) && !bFound)
224c120c564SAndrew Turner     {
225c120c564SAndrew Turner         if( (*it)->addrInRange(address) &&
226c120c564SAndrew Turner             (*it)->inMemSpace(mem_space))
227c120c564SAndrew Turner         {
228c120c564SAndrew Turner             bFound = true;
229c120c564SAndrew Turner             m_acc_curr = *it;
230c120c564SAndrew Turner         }
231c120c564SAndrew Turner         it++;
232c120c564SAndrew Turner     }
233c120c564SAndrew Turner     return bFound;
234c120c564SAndrew Turner }
235c120c564SAndrew Turner 
readFromCurrent(const ocsd_vaddr_t address,const ocsd_mem_space_acc_t mem_space,const uint8_t)236c120c564SAndrew Turner bool TrcMemAccMapGlobalSpace::readFromCurrent(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t /*cs_trace_id*/)
237c120c564SAndrew Turner {
238c120c564SAndrew Turner     bool readFromCurr = false;
239c120c564SAndrew Turner     if(m_acc_curr)
240c120c564SAndrew Turner         readFromCurr = (m_acc_curr->addrInRange(address) && m_acc_curr->inMemSpace(mem_space));
241c120c564SAndrew Turner     return readFromCurr;
242c120c564SAndrew Turner }
243c120c564SAndrew Turner 
244c120c564SAndrew Turner 
getFirstAccessor()245c120c564SAndrew Turner TrcMemAccessorBase * TrcMemAccMapGlobalSpace::getFirstAccessor()
246c120c564SAndrew Turner {
247c120c564SAndrew Turner     TrcMemAccessorBase *p_acc = 0;
248c120c564SAndrew Turner     m_acc_it = m_acc_global.begin();
249c120c564SAndrew Turner     if(m_acc_it != m_acc_global.end())
250c120c564SAndrew Turner     {
251c120c564SAndrew Turner         p_acc = *m_acc_it;
252c120c564SAndrew Turner     }
253c120c564SAndrew Turner     return p_acc;
254c120c564SAndrew Turner }
255c120c564SAndrew Turner 
getNextAccessor()256c120c564SAndrew Turner TrcMemAccessorBase *TrcMemAccMapGlobalSpace::getNextAccessor()
257c120c564SAndrew Turner {
258c120c564SAndrew Turner     TrcMemAccessorBase *p_acc = 0;
259c120c564SAndrew Turner     m_acc_it++;
260c120c564SAndrew Turner     if(m_acc_it != m_acc_global.end())
261c120c564SAndrew Turner     {
262c120c564SAndrew Turner         p_acc = *m_acc_it;
263c120c564SAndrew Turner     }
264c120c564SAndrew Turner     return p_acc;
265c120c564SAndrew Turner }
266c120c564SAndrew Turner 
clearAccessorList()267c120c564SAndrew Turner void TrcMemAccMapGlobalSpace::clearAccessorList()
268c120c564SAndrew Turner {
269c120c564SAndrew Turner     m_acc_global.clear();
270c120c564SAndrew Turner }
271c120c564SAndrew Turner 
RemoveAccessor(const TrcMemAccessorBase * p_accessor)272c120c564SAndrew Turner ocsd_err_t TrcMemAccMapGlobalSpace::RemoveAccessor(const TrcMemAccessorBase *p_accessor)
273c120c564SAndrew Turner {
274c120c564SAndrew Turner     bool bFound = false;
275c120c564SAndrew Turner     TrcMemAccessorBase *p_acc = getFirstAccessor();
276c120c564SAndrew Turner     while(p_acc != 0)
277c120c564SAndrew Turner     {
278c120c564SAndrew Turner         if(p_acc == p_accessor)
279c120c564SAndrew Turner         {
280c120c564SAndrew Turner             m_acc_global.erase(m_acc_it);
281c120c564SAndrew Turner             TrcMemAccFactory::DestroyAccessor(p_acc);
282c120c564SAndrew Turner             p_acc = 0;
283c120c564SAndrew Turner             bFound = true;
284c120c564SAndrew Turner         }
285c120c564SAndrew Turner         else
286c120c564SAndrew Turner             p_acc = getNextAccessor();
287c120c564SAndrew Turner     }
288c120c564SAndrew Turner     return bFound ? OCSD_OK : OCSD_ERR_INVALID_PARAM_VAL;
289c120c564SAndrew Turner }
290c120c564SAndrew Turner 
291c120c564SAndrew Turner 
logMappedRanges()292c120c564SAndrew Turner void TrcMemAccMapGlobalSpace::logMappedRanges()
293c120c564SAndrew Turner {
294c120c564SAndrew Turner     std::string accStr;
295c120c564SAndrew Turner     TrcMemAccessorBase *pAccessor = getFirstAccessor();
296c120c564SAndrew Turner     LogMessage("Mapped Memory Accessors\n");
297c120c564SAndrew Turner     while(pAccessor != 0)
298c120c564SAndrew Turner     {
299c120c564SAndrew Turner         pAccessor->getMemAccString(accStr);
300c120c564SAndrew Turner         accStr += "\n";
301c120c564SAndrew Turner         LogMessage(accStr);
302c120c564SAndrew Turner         pAccessor = getNextAccessor();
303c120c564SAndrew Turner     }
304c120c564SAndrew Turner     LogMessage("========================\n");
305c120c564SAndrew Turner }
306c120c564SAndrew Turner 
307c120c564SAndrew Turner /* End of File trc_mem_acc_mapper.cpp */
308