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