cpu.cc revision 12749
1/* 2 * Copyright (c) 2011,2013,2017 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2006 The Regents of The University of Michigan 15 * All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions are 19 * met: redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer; 21 * redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution; 24 * neither the name of the copyright holders nor the names of its 25 * contributors may be used to endorse or promote products derived from 26 * this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 * 40 * Authors: Kevin Lim 41 * Geoffrey Blake 42 */ 43 44#include "cpu/checker/cpu.hh" 45 46#include <list> 47#include <string> 48 49#include "arch/generic/tlb.hh" 50#include "arch/kernel_stats.hh" 51#include "arch/vtophys.hh" 52#include "cpu/base.hh" 53#include "cpu/simple_thread.hh" 54#include "cpu/static_inst.hh" 55#include "cpu/thread_context.hh" 56#include "params/CheckerCPU.hh" 57#include "sim/full_system.hh" 58 59using namespace std; 60using namespace TheISA; 61 62void 63CheckerCPU::init() 64{ 65 masterId = systemPtr->getMasterId(this); 66} 67 68CheckerCPU::CheckerCPU(Params *p) 69 : BaseCPU(p, true), systemPtr(NULL), icachePort(NULL), dcachePort(NULL), 70 tc(NULL), thread(NULL) 71{ 72 curStaticInst = NULL; 73 curMacroStaticInst = NULL; 74 75 numInst = 0; 76 startNumInst = 0; 77 numLoad = 0; 78 startNumLoad = 0; 79 youngestSN = 0; 80 81 changedPC = willChangePC = false; 82 83 exitOnError = p->exitOnError; 84 warnOnlyOnLoadError = p->warnOnlyOnLoadError; 85 itb = p->itb; 86 dtb = p->dtb; 87 workload = p->workload; 88 89 updateOnError = true; 90} 91 92CheckerCPU::~CheckerCPU() 93{ 94} 95 96void 97CheckerCPU::setSystem(System *system) 98{ 99 const Params *p(dynamic_cast<const Params *>(_params)); 100 101 systemPtr = system; 102 103 if (FullSystem) { 104 thread = new SimpleThread(this, 0, systemPtr, itb, dtb, 105 p->isa[0], false); 106 } else { 107 thread = new SimpleThread(this, 0, systemPtr, 108 workload.size() ? workload[0] : NULL, 109 itb, dtb, p->isa[0]); 110 } 111 112 tc = thread->getTC(); 113 threadContexts.push_back(tc); 114 thread->kernelStats = NULL; 115 // Thread should never be null after this 116 assert(thread != NULL); 117} 118 119void 120CheckerCPU::setIcachePort(MasterPort *icache_port) 121{ 122 icachePort = icache_port; 123} 124 125void 126CheckerCPU::setDcachePort(MasterPort *dcache_port) 127{ 128 dcachePort = dcache_port; 129} 130 131void 132CheckerCPU::serialize(ostream &os) const 133{ 134} 135 136void 137CheckerCPU::unserialize(CheckpointIn &cp) 138{ 139} 140 141Fault 142CheckerCPU::readMem(Addr addr, uint8_t *data, unsigned size, 143 Request::Flags flags) 144{ 145 Fault fault = NoFault; 146 int fullSize = size; 147 Addr secondAddr = roundDown(addr + size - 1, cacheLineSize()); 148 bool checked_flags = false; 149 bool flags_match = true; 150 Addr pAddr = 0x0; 151 152 153 if (secondAddr > addr) 154 size = secondAddr - addr; 155 156 // Need to account for multiple accesses like the Atomic and TimingSimple 157 while (1) { 158 auto mem_req = std::make_shared<Request>( 159 0, addr, size, flags, masterId, 160 thread->pcState().instAddr(), tc->contextId()); 161 162 // translate to physical address 163 fault = dtb->translateFunctional(mem_req, tc, BaseTLB::Read); 164 165 if (!checked_flags && fault == NoFault && unverifiedReq) { 166 flags_match = checkFlags(unverifiedReq, mem_req->getVaddr(), 167 mem_req->getPaddr(), mem_req->getFlags()); 168 pAddr = mem_req->getPaddr(); 169 checked_flags = true; 170 } 171 172 // Now do the access 173 if (fault == NoFault && 174 !mem_req->getFlags().isSet(Request::NO_ACCESS)) { 175 PacketPtr pkt = Packet::createRead(mem_req); 176 177 pkt->dataStatic(data); 178 179 if (!(mem_req->isUncacheable() || mem_req->isMmappedIpr())) { 180 // Access memory to see if we have the same data 181 dcachePort->sendFunctional(pkt); 182 } else { 183 // Assume the data is correct if it's an uncached access 184 memcpy(data, unverifiedMemData, size); 185 } 186 187 delete pkt; 188 } 189 190 if (fault != NoFault) { 191 if (mem_req->isPrefetch()) { 192 fault = NoFault; 193 } 194 break; 195 } 196 197 //If we don't need to access a second cache line, stop now. 198 if (secondAddr <= addr) 199 { 200 break; 201 } 202 203 // Setup for accessing next cache line 204 data += size; 205 unverifiedMemData += size; 206 size = addr + fullSize - secondAddr; 207 addr = secondAddr; 208 } 209 210 if (!flags_match) { 211 warn("%lli: Flags do not match CPU:%#x %#x %#x Checker:%#x %#x %#x\n", 212 curTick(), unverifiedReq->getVaddr(), unverifiedReq->getPaddr(), 213 unverifiedReq->getFlags(), addr, pAddr, flags); 214 handleError(); 215 } 216 217 return fault; 218} 219 220Fault 221CheckerCPU::writeMem(uint8_t *data, unsigned size, 222 Addr addr, Request::Flags flags, uint64_t *res) 223{ 224 Fault fault = NoFault; 225 bool checked_flags = false; 226 bool flags_match = true; 227 Addr pAddr = 0x0; 228 static uint8_t zero_data[64] = {}; 229 230 int fullSize = size; 231 232 Addr secondAddr = roundDown(addr + size - 1, cacheLineSize()); 233 234 if (secondAddr > addr) 235 size = secondAddr - addr; 236 237 // Need to account for a multiple access like Atomic and Timing CPUs 238 while (1) { 239 auto mem_req = std::make_shared<Request>( 240 0, addr, size, flags, masterId, 241 thread->pcState().instAddr(), tc->contextId()); 242 243 // translate to physical address 244 fault = dtb->translateFunctional(mem_req, tc, BaseTLB::Write); 245 246 if (!checked_flags && fault == NoFault && unverifiedReq) { 247 flags_match = checkFlags(unverifiedReq, mem_req->getVaddr(), 248 mem_req->getPaddr(), mem_req->getFlags()); 249 pAddr = mem_req->getPaddr(); 250 checked_flags = true; 251 } 252 253 /* 254 * We don't actually check memory for the store because there 255 * is no guarantee it has left the lsq yet, and therefore we 256 * can't verify the memory on stores without lsq snooping 257 * enabled. This is left as future work for the Checker: LSQ snooping 258 * and memory validation after stores have committed. 259 */ 260 bool was_prefetch = mem_req->isPrefetch(); 261 262 //If we don't need to access a second cache line, stop now. 263 if (fault != NoFault || secondAddr <= addr) 264 { 265 if (fault != NoFault && was_prefetch) { 266 fault = NoFault; 267 } 268 break; 269 } 270 271 //Update size and access address 272 size = addr + fullSize - secondAddr; 273 //And access the right address. 274 addr = secondAddr; 275 } 276 277 if (!flags_match) { 278 warn("%lli: Flags do not match CPU:%#x %#x Checker:%#x %#x %#x\n", 279 curTick(), unverifiedReq->getVaddr(), unverifiedReq->getPaddr(), 280 unverifiedReq->getFlags(), addr, pAddr, flags); 281 handleError(); 282 } 283 284 // Assume the result was the same as the one passed in. This checker 285 // doesn't check if the SC should succeed or fail, it just checks the 286 // value. 287 if (unverifiedReq && res && unverifiedReq->extraDataValid()) 288 *res = unverifiedReq->getExtraData(); 289 290 // Entire purpose here is to make sure we are getting the 291 // same data to send to the mem system as the CPU did. 292 // Cannot check this is actually what went to memory because 293 // there stores can be in ld/st queue or coherent operations 294 // overwriting values. 295 bool extraData = false; 296 if (unverifiedReq) { 297 extraData = unverifiedReq->extraDataValid() ? 298 unverifiedReq->getExtraData() : true; 299 } 300 301 // If the request is to ZERO a cache block, there is no data to check 302 // against, but it's all zero. We need something to compare to, so use a 303 // const set of zeros. 304 if (flags & Request::STORE_NO_DATA) { 305 assert(!data); 306 assert(sizeof(zero_data) <= fullSize); 307 data = zero_data; 308 } 309 310 if (unverifiedReq && unverifiedMemData && 311 memcmp(data, unverifiedMemData, fullSize) && extraData) { 312 warn("%lli: Store value does not match value sent to memory! " 313 "data: %#x inst_data: %#x", curTick(), data, 314 unverifiedMemData); 315 handleError(); 316 } 317 318 return fault; 319} 320 321Addr 322CheckerCPU::dbg_vtophys(Addr addr) 323{ 324 return vtophys(tc, addr); 325} 326 327/** 328 * Checks if the flags set by the Checker and Checkee match. 329 */ 330bool 331CheckerCPU::checkFlags(const RequestPtr &unverified_req, Addr vAddr, 332 Addr pAddr, int flags) 333{ 334 Addr unverifiedVAddr = unverified_req->getVaddr(); 335 Addr unverifiedPAddr = unverified_req->getPaddr(); 336 int unverifiedFlags = unverified_req->getFlags(); 337 338 if (unverifiedVAddr != vAddr || 339 unverifiedPAddr != pAddr || 340 unverifiedFlags != flags) { 341 return false; 342 } 343 344 return true; 345} 346 347void 348CheckerCPU::dumpAndExit() 349{ 350 warn("%lli: Checker PC:%s", 351 curTick(), thread->pcState()); 352 panic("Checker found an error!"); 353} 354