blob: 7cd57fe5715b732fbbee66546e544ac702e89ae1 [file]
/*
* \file trc_mem_acc_mapper.cpp
* \brief OpenCSD :
*
* \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved.
*/
/*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "mem_acc/trc_mem_acc_mapper.h"
#include "mem_acc/trc_mem_acc_file.h"
#include "common/ocsd_error.h"
/************************************************************************************/
/* mappers base class */
/************************************************************************************/
TrcMemAccMapper::TrcMemAccMapper() :
m_acc_curr(0),
m_trace_id_curr(0),
m_using_trace_id(false),
m_err_log(0)
{
}
TrcMemAccMapper::TrcMemAccMapper(bool using_trace_id) :
m_acc_curr(0),
m_trace_id_curr(0),
m_using_trace_id(using_trace_id),
m_err_log(0)
{
}
TrcMemAccMapper::~TrcMemAccMapper()
{
}
void TrcMemAccMapper::setErrorLog(ITraceErrorLog *err_log_i)
{
m_err_log = err_log_i;
m_cache.setErrorLog(err_log_i);
}
ocsd_err_t TrcMemAccMapper::enableCaching(bool bEnable)
{
return m_cache.enableCaching(bEnable);
}
// set cache page size and number of pages (max 4096 size, 256 pages)
ocsd_err_t TrcMemAccMapper::setCacheSizes(uint16_t page_size, int num_pages, const bool err_on_limit /*= false*/)
{
return m_cache.setCacheSizes(page_size, num_pages, err_on_limit);
}
// memory access interface
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)
{
bool bReadFromCurr = true;
uint32_t readBytes = 0;
ocsd_err_t err = OCSD_OK;
/* see if the address is in any range we know */
if (!readFromCurrent(address, mem_space, cs_trace_id))
{
bReadFromCurr = findAccessor(address, mem_space, cs_trace_id);
// found a new accessor - invalidate any cache entries used by the previous one.
if (m_cache.enabled() && bReadFromCurr)
m_cache.invalidateByTraceID(cs_trace_id);
}
/* if bReadFromCurr then we know m_acc_curr is set */
if (bReadFromCurr)
{
// use cache if enabled and the amount fits into a cache page
if (m_cache.enabled_for_size(*num_bytes))
{
// read from cache - or load a new cache page and read....
readBytes = *num_bytes;
err = m_cache.readBytesFromCache(m_acc_curr, address, mem_space, cs_trace_id, &readBytes, p_buffer);
if (err != OCSD_OK)
LogWarn(err, "Mem Acc: Cache access error");
}
else
{
readBytes = m_acc_curr->readBytes(address, mem_space, cs_trace_id, *num_bytes, p_buffer);
// guard against bad accessor returns (e.g. callback not obeying the rules for return values)
if (readBytes > *num_bytes)
{
err = OCSD_ERR_MEM_ACC_BAD_LEN;
LogWarn(err,"Mem acc: bad return length");
}
}
}
*num_bytes = readBytes;
return err;
}
void TrcMemAccMapper::InvalidateMemAccCache(const uint8_t cs_trace_id)
{
if (m_cache.enabled())
m_cache.invalidateByTraceID(cs_trace_id);
}
void TrcMemAccMapper::RemoveAllAccessors()
{
clearAccessorList();
if (m_cache.enabled())
{
m_cache.invalidateAll();
m_cache.logAndClearCounts();
}
}
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 */)
{
ocsd_err_t err = OCSD_OK;
if(findAccessor(st_address,mem_space,cs_trace_id))
{
err = RemoveAccessor(m_acc_curr);
m_acc_curr = 0;
if (m_cache.enabled())
{
m_cache.invalidateAll();
m_cache.logAndClearCounts();
}
}
else
err = OCSD_ERR_INVALID_PARAM_VAL;
return err;
}
void TrcMemAccMapper::LogMessage(const std::string &msg)
{
if(m_err_log)
m_err_log->LogMessage(ITraceErrorLog::HANDLE_GEN_INFO,OCSD_ERR_SEV_INFO,msg);
}
void TrcMemAccMapper::LogWarn(const ocsd_err_t err, const std::string &msg)
{
if (m_err_log)
{
ocsdError err_ocsd(OCSD_ERR_SEV_WARN,err,msg);
m_err_log->LogError(ITraceErrorLog::HANDLE_GEN_INFO, &err_ocsd);
}
}
/************************************************************************************/
/* mappers global address space class - no differentiation in core trace IDs */
/************************************************************************************/
TrcMemAccMapGlobalSpace::TrcMemAccMapGlobalSpace() : TrcMemAccMapper()
{
}
TrcMemAccMapGlobalSpace::~TrcMemAccMapGlobalSpace()
{
}
ocsd_err_t TrcMemAccMapGlobalSpace::AddAccessor(TrcMemAccessorBase *p_accessor, const uint8_t /*cs_trace_id*/)
{
ocsd_err_t err = OCSD_OK;
bool bOverLap = false;
if(!p_accessor->validateRange())
return OCSD_ERR_MEM_ACC_RANGE_INVALID;
std::vector<TrcMemAccessorBase *>::const_iterator it = m_acc_global.begin();
while((it != m_acc_global.end()) && !bOverLap)
{
// if overlap and memory space match
if( ((*it)->overLapRange(p_accessor)) &&
((*it)->inMemSpace(p_accessor->getMemSpace()))
)
{
bOverLap = true;
err = OCSD_ERR_MEM_ACC_OVERLAP;
}
it++;
}
// no overlap - add to the list of ranges.
if(!bOverLap)
m_acc_global.push_back(p_accessor);
return err;
}
bool TrcMemAccMapGlobalSpace::findAccessor(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t /*cs_trace_id*/)
{
bool bFound = false;
std::vector<TrcMemAccessorBase *>::const_iterator it = m_acc_global.begin();
while((it != m_acc_global.end()) && !bFound)
{
if( (*it)->addrInRange(address) &&
(*it)->inMemSpace(mem_space))
{
bFound = true;
m_acc_curr = *it;
}
it++;
}
return bFound;
}
bool TrcMemAccMapGlobalSpace::readFromCurrent(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t /*cs_trace_id*/)
{
bool readFromCurr = false;
if(m_acc_curr)
readFromCurr = (m_acc_curr->addrInRange(address) && m_acc_curr->inMemSpace(mem_space));
return readFromCurr;
}
TrcMemAccessorBase * TrcMemAccMapGlobalSpace::getFirstAccessor()
{
TrcMemAccessorBase *p_acc = 0;
m_acc_it = m_acc_global.begin();
if(m_acc_it != m_acc_global.end())
{
p_acc = *m_acc_it;
}
return p_acc;
}
TrcMemAccessorBase *TrcMemAccMapGlobalSpace::getNextAccessor()
{
TrcMemAccessorBase *p_acc = 0;
m_acc_it++;
if(m_acc_it != m_acc_global.end())
{
p_acc = *m_acc_it;
}
return p_acc;
}
void TrcMemAccMapGlobalSpace::clearAccessorList()
{
m_acc_global.clear();
m_acc_curr = 0;
}
ocsd_err_t TrcMemAccMapGlobalSpace::RemoveAccessor(const TrcMemAccessorBase *p_accessor)
{
bool bFound = false;
TrcMemAccessorBase *p_acc = getFirstAccessor();
while(p_acc != 0)
{
if(p_acc == p_accessor)
{
m_acc_global.erase(m_acc_it);
p_acc = 0;
bFound = true;
if (m_cache.enabled())
{
m_cache.invalidateAll();
m_cache.logAndClearCounts();
}
if (m_acc_curr == p_accessor)
m_acc_curr = 0;
}
else
p_acc = getNextAccessor();
}
return bFound ? OCSD_OK : OCSD_ERR_INVALID_PARAM_VAL;
}
void TrcMemAccMapGlobalSpace::logMappedRanges()
{
std::string accStr;
TrcMemAccessorBase *pAccessor = getFirstAccessor();
LogMessage("Mapped Memory Accessors\n");
while(pAccessor != 0)
{
pAccessor->getMemAccString(accStr);
accStr += "\n";
LogMessage(accStr);
pAccessor = getNextAccessor();
}
LogMessage("========================\n");
}
/* End of File trc_mem_acc_mapper.cpp */