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::RemoveAllAccessors() 123 { 124 TrcMemAccessorBase *pAcc = 0; 125 pAcc = getFirstAccessor(); 126 while(pAcc != 0) 127 { 128 TrcMemAccFactory::DestroyAccessor(pAcc); 129 pAcc = getNextAccessor(); 130 if (m_cache.enabled()) 131 m_cache.invalidateAll(); 132 } 133 clearAccessorList(); 134 if (m_cache.enabled()) 135 m_cache.logAndClearCounts(); 136 } 137 138 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 */) 139 { 140 ocsd_err_t err = OCSD_OK; 141 if(findAccessor(st_address,mem_space,cs_trace_id)) 142 { 143 err = RemoveAccessor(m_acc_curr); 144 m_acc_curr = 0; 145 if (m_cache.enabled()) 146 m_cache.invalidateAll(); 147 } 148 else 149 err = OCSD_ERR_INVALID_PARAM_VAL; 150 if (m_cache.enabled()) 151 m_cache.logAndClearCounts(); 152 return err; 153 } 154 155 void TrcMemAccMapper::LogMessage(const std::string &msg) 156 { 157 if(m_err_log) 158 m_err_log->LogMessage(ITraceErrorLog::HANDLE_GEN_INFO,OCSD_ERR_SEV_INFO,msg); 159 } 160 161 void TrcMemAccMapper::LogWarn(const ocsd_err_t err, const std::string &msg) 162 { 163 if (m_err_log) 164 { 165 ocsdError err_ocsd(OCSD_ERR_SEV_WARN,err,msg); 166 m_err_log->LogError(ITraceErrorLog::HANDLE_GEN_INFO, &err_ocsd); 167 } 168 } 169 170 171 /************************************************************************************/ 172 /* mappers global address space class - no differentiation in core trace IDs */ 173 /************************************************************************************/ 174 TrcMemAccMapGlobalSpace::TrcMemAccMapGlobalSpace() : TrcMemAccMapper() 175 { 176 } 177 178 TrcMemAccMapGlobalSpace::~TrcMemAccMapGlobalSpace() 179 { 180 } 181 182 ocsd_err_t TrcMemAccMapGlobalSpace::AddAccessor(TrcMemAccessorBase *p_accessor, const uint8_t /*cs_trace_id*/) 183 { 184 ocsd_err_t err = OCSD_OK; 185 bool bOverLap = false; 186 187 if(!p_accessor->validateRange()) 188 return OCSD_ERR_MEM_ACC_RANGE_INVALID; 189 190 std::vector<TrcMemAccessorBase *>::const_iterator it = m_acc_global.begin(); 191 while((it != m_acc_global.end()) && !bOverLap) 192 { 193 // if overlap and memory space match 194 if( ((*it)->overLapRange(p_accessor)) && 195 ((*it)->inMemSpace(p_accessor->getMemSpace())) 196 ) 197 { 198 bOverLap = true; 199 err = OCSD_ERR_MEM_ACC_OVERLAP; 200 } 201 it++; 202 } 203 204 // no overlap - add to the list of ranges. 205 if(!bOverLap) 206 m_acc_global.push_back(p_accessor); 207 208 return err; 209 } 210 211 bool TrcMemAccMapGlobalSpace::findAccessor(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t /*cs_trace_id*/) 212 { 213 bool bFound = false; 214 std::vector<TrcMemAccessorBase *>::const_iterator it = m_acc_global.begin(); 215 while((it != m_acc_global.end()) && !bFound) 216 { 217 if( (*it)->addrInRange(address) && 218 (*it)->inMemSpace(mem_space)) 219 { 220 bFound = true; 221 m_acc_curr = *it; 222 } 223 it++; 224 } 225 return bFound; 226 } 227 228 bool TrcMemAccMapGlobalSpace::readFromCurrent(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t /*cs_trace_id*/) 229 { 230 bool readFromCurr = false; 231 if(m_acc_curr) 232 readFromCurr = (m_acc_curr->addrInRange(address) && m_acc_curr->inMemSpace(mem_space)); 233 return readFromCurr; 234 } 235 236 237 TrcMemAccessorBase * TrcMemAccMapGlobalSpace::getFirstAccessor() 238 { 239 TrcMemAccessorBase *p_acc = 0; 240 m_acc_it = m_acc_global.begin(); 241 if(m_acc_it != m_acc_global.end()) 242 { 243 p_acc = *m_acc_it; 244 } 245 return p_acc; 246 } 247 248 TrcMemAccessorBase *TrcMemAccMapGlobalSpace::getNextAccessor() 249 { 250 TrcMemAccessorBase *p_acc = 0; 251 m_acc_it++; 252 if(m_acc_it != m_acc_global.end()) 253 { 254 p_acc = *m_acc_it; 255 } 256 return p_acc; 257 } 258 259 void TrcMemAccMapGlobalSpace::clearAccessorList() 260 { 261 m_acc_global.clear(); 262 } 263 264 ocsd_err_t TrcMemAccMapGlobalSpace::RemoveAccessor(const TrcMemAccessorBase *p_accessor) 265 { 266 bool bFound = false; 267 TrcMemAccessorBase *p_acc = getFirstAccessor(); 268 while(p_acc != 0) 269 { 270 if(p_acc == p_accessor) 271 { 272 m_acc_global.erase(m_acc_it); 273 TrcMemAccFactory::DestroyAccessor(p_acc); 274 p_acc = 0; 275 bFound = true; 276 } 277 else 278 p_acc = getNextAccessor(); 279 } 280 return bFound ? OCSD_OK : OCSD_ERR_INVALID_PARAM_VAL; 281 } 282 283 284 void TrcMemAccMapGlobalSpace::logMappedRanges() 285 { 286 std::string accStr; 287 TrcMemAccessorBase *pAccessor = getFirstAccessor(); 288 LogMessage("Mapped Memory Accessors\n"); 289 while(pAccessor != 0) 290 { 291 pAccessor->getMemAccString(accStr); 292 accStr += "\n"; 293 LogMessage(accStr); 294 pAccessor = getNextAccessor(); 295 } 296 LogMessage("========================\n"); 297 } 298 299 /* End of File trc_mem_acc_mapper.cpp */ 300