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