cpu.cc revision 8733
19157Sandreas.hansson@arm.com/* 29793Sakash.bagdia@arm.com * Copyright (c) 2011 ARM Limited 310000Sclt67@cornell.edu * All rights reserved 49157Sandreas.hansson@arm.com * 59157Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall 69157Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual 79157Sandreas.hansson@arm.com * property including but not limited to intellectual property relating 89157Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software 99157Sandreas.hansson@arm.com * licensed hereunder. You may use the software subject to the license 109157Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated 119157Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software, 129157Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form. 139157Sandreas.hansson@arm.com * 149157Sandreas.hansson@arm.com * Copyright (c) 2006 The Regents of The University of Michigan 159157Sandreas.hansson@arm.com * All rights reserved. 169157Sandreas.hansson@arm.com * 179157Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 189157Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 199157Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 209157Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 219157Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 229157Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 239157Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 249157Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 259157Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 269157Sandreas.hansson@arm.com * this software without specific prior written permission. 279157Sandreas.hansson@arm.com * 289157Sandreas.hansson@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 299157Sandreas.hansson@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 309157Sandreas.hansson@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 319157Sandreas.hansson@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 329157Sandreas.hansson@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 339157Sandreas.hansson@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 349157Sandreas.hansson@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 359157Sandreas.hansson@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 369157Sandreas.hansson@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 379157Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 389157Sandreas.hansson@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3910000Sclt67@cornell.edu * 409157Sandreas.hansson@arm.com * Authors: Kevin Lim 419157Sandreas.hansson@arm.com * Geoffrey Blake 429157Sandreas.hansson@arm.com */ 439157Sandreas.hansson@arm.com 449157Sandreas.hansson@arm.com#include <list> 459157Sandreas.hansson@arm.com#include <string> 469157Sandreas.hansson@arm.com 479157Sandreas.hansson@arm.com#include "cpu/checker/cpu.hh" 489157Sandreas.hansson@arm.com#include "cpu/base.hh" 499157Sandreas.hansson@arm.com#include "cpu/simple_thread.hh" 509157Sandreas.hansson@arm.com#include "cpu/static_inst.hh" 519418Sandreas.hansson@arm.com#include "cpu/thread_context.hh" 529157Sandreas.hansson@arm.com#include "params/CheckerCPU.hh" 539356Snilay@cs.wisc.edu#include "sim/tlb.hh" 549793Sakash.bagdia@arm.com 559157Sandreas.hansson@arm.com#if FULL_SYSTEM 569157Sandreas.hansson@arm.com#include "arch/kernel_stats.hh" 579157Sandreas.hansson@arm.com#include "arch/vtophys.hh" 589157Sandreas.hansson@arm.com#endif // FULL_SYSTEM 599157Sandreas.hansson@arm.com 609157Sandreas.hansson@arm.comusing namespace std; 619157Sandreas.hansson@arm.comusing namespace TheISA; 629157Sandreas.hansson@arm.com 639157Sandreas.hansson@arm.comvoid 649157Sandreas.hansson@arm.comCheckerCPU::init() 659157Sandreas.hansson@arm.com{ 669179Sandreas.hansson@arm.com} 679179Sandreas.hansson@arm.com 689179Sandreas.hansson@arm.comCheckerCPU::CheckerCPU(Params *p) 699179Sandreas.hansson@arm.com : BaseCPU(p), thread(NULL), tc(NULL) 709179Sandreas.hansson@arm.com{ 719179Sandreas.hansson@arm.com memReq = NULL; 729180Sandreas.hansson@arm.com curStaticInst = NULL; 739179Sandreas.hansson@arm.com curMacroStaticInst = NULL; 749157Sandreas.hansson@arm.com 759157Sandreas.hansson@arm.com numInst = 0; 769157Sandreas.hansson@arm.com startNumInst = 0; 779157Sandreas.hansson@arm.com numLoad = 0; 789157Sandreas.hansson@arm.com startNumLoad = 0; 799157Sandreas.hansson@arm.com youngestSN = 0; 809157Sandreas.hansson@arm.com 819179Sandreas.hansson@arm.com changedPC = willChangePC = changedNextPC = false; 8210236Sjthestness@gmail.com 8310236Sjthestness@gmail.com exitOnError = p->exitOnError; 849179Sandreas.hansson@arm.com warnOnlyOnLoadError = p->warnOnlyOnLoadError; 859179Sandreas.hansson@arm.com itb = p->itb; 869179Sandreas.hansson@arm.com dtb = p->dtb; 879179Sandreas.hansson@arm.com#if FULL_SYSTEM 889179Sandreas.hansson@arm.com systemPtr = NULL; 899179Sandreas.hansson@arm.com#else 909179Sandreas.hansson@arm.com workload = p->workload; 919179Sandreas.hansson@arm.com // XXX: This is a hack to get this to work some 929179Sandreas.hansson@arm.com thread = new SimpleThread(this, /* thread_num */ 0, workload[0], itb, dtb); 939179Sandreas.hansson@arm.com 949179Sandreas.hansson@arm.com tc = thread->getTC(); 959793Sakash.bagdia@arm.com threadContexts.push_back(tc); 969179Sandreas.hansson@arm.com#endif 979179Sandreas.hansson@arm.com 989179Sandreas.hansson@arm.com updateOnError = true; 999179Sandreas.hansson@arm.com} 1009179Sandreas.hansson@arm.com 1019179Sandreas.hansson@arm.comCheckerCPU::~CheckerCPU() 1029179Sandreas.hansson@arm.com{ 1039179Sandreas.hansson@arm.com} 1049179Sandreas.hansson@arm.com 1059793Sakash.bagdia@arm.comvoid 1069179Sandreas.hansson@arm.comCheckerCPU::setSystem(System *system) 1079793Sakash.bagdia@arm.com{ 1089179Sandreas.hansson@arm.com#if FULL_SYSTEM 1099179Sandreas.hansson@arm.com systemPtr = system; 1109793Sakash.bagdia@arm.com 1119793Sakash.bagdia@arm.com thread = new SimpleThread(this, 0, systemPtr, itb, dtb, false); 1129793Sakash.bagdia@arm.com 1139793Sakash.bagdia@arm.com tc = thread->getTC(); 1149157Sandreas.hansson@arm.com threadContexts.push_back(tc); 1159545Sandreas.hansson@arm.com delete thread->kernelStats; 1169545Sandreas.hansson@arm.com thread->kernelStats = NULL; 1179157Sandreas.hansson@arm.com#endif 1189793Sakash.bagdia@arm.com} 1199157Sandreas.hansson@arm.com 1209157Sandreas.hansson@arm.comvoid 1219179Sandreas.hansson@arm.comCheckerCPU::setIcachePort(Port *icache_port) 1229793Sakash.bagdia@arm.com{ 1239418Sandreas.hansson@arm.com icachePort = icache_port; 12410000Sclt67@cornell.edu} 12510000Sclt67@cornell.edu 12610000Sclt67@cornell.eduvoid 1279418Sandreas.hansson@arm.comCheckerCPU::setDcachePort(Port *dcache_port) 1289157Sandreas.hansson@arm.com{ 1299157Sandreas.hansson@arm.com dcachePort = dcache_port; 1309157Sandreas.hansson@arm.com} 1319157Sandreas.hansson@arm.com 1329157Sandreas.hansson@arm.comvoid 1339157Sandreas.hansson@arm.comCheckerCPU::serialize(ostream &os) 1349296Snilay@cs.wisc.edu{ 1359296Snilay@cs.wisc.edu} 1369296Snilay@cs.wisc.edu 1379296Snilay@cs.wisc.eduvoid 1389296Snilay@cs.wisc.eduCheckerCPU::unserialize(Checkpoint *cp, const string §ion) 1399296Snilay@cs.wisc.edu{ 1409296Snilay@cs.wisc.edu} 1419793Sakash.bagdia@arm.com 1429296Snilay@cs.wisc.eduFault 1439793Sakash.bagdia@arm.comCheckerCPU::readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags) 1449296Snilay@cs.wisc.edu{ 1459296Snilay@cs.wisc.edu Fault fault = NoFault; 1469157Sandreas.hansson@arm.com unsigned blockSize = dcachePort->peerBlockSize(); 1479157Sandreas.hansson@arm.com int fullSize = size; 1489157Sandreas.hansson@arm.com Addr secondAddr = roundDown(addr + size - 1, blockSize); 14910000Sclt67@cornell.edu bool checked_flags = false; 15010000Sclt67@cornell.edu bool flags_match = true; 15110000Sclt67@cornell.edu Addr pAddr = 0x0; 15210000Sclt67@cornell.edu 15310000Sclt67@cornell.edu 15410000Sclt67@cornell.edu if (secondAddr > addr) 15510000Sclt67@cornell.edu size = secondAddr - addr; 15610000Sclt67@cornell.edu 15710000Sclt67@cornell.edu // Need to account for multiple accesses like the Atomic and TimingSimple 15810236Sjthestness@gmail.com while (1) { 15910236Sjthestness@gmail.com memReq = new Request(); 16010236Sjthestness@gmail.com memReq->setVirt(0, addr, size, flags, thread->pcState().instAddr()); 16110236Sjthestness@gmail.com 16210236Sjthestness@gmail.com // translate to physical address 16310236Sjthestness@gmail.com fault = dtb->translateFunctional(memReq, tc, BaseTLB::Read); 1649179Sandreas.hansson@arm.com 1659179Sandreas.hansson@arm.com if (!checked_flags && fault == NoFault && unverifiedReq) { 1669179Sandreas.hansson@arm.com flags_match = checkFlags(unverifiedReq, memReq->getVaddr(), 16710236Sjthestness@gmail.com memReq->getPaddr(), memReq->getFlags()); 16810236Sjthestness@gmail.com pAddr = memReq->getPaddr(); 16910236Sjthestness@gmail.com checked_flags = true; 1709179Sandreas.hansson@arm.com } 1719180Sandreas.hansson@arm.com 1729179Sandreas.hansson@arm.com // Now do the access 1739179Sandreas.hansson@arm.com if (fault == NoFault && 1749179Sandreas.hansson@arm.com !memReq->getFlags().isSet(Request::NO_ACCESS)) { 1759179Sandreas.hansson@arm.com PacketPtr pkt = new Packet(memReq, 1769179Sandreas.hansson@arm.com memReq->isLLSC() ? 1779793Sakash.bagdia@arm.com MemCmd::LoadLockedReq : MemCmd::ReadReq, 1789179Sandreas.hansson@arm.com Packet::Broadcast); 1799179Sandreas.hansson@arm.com 1809179Sandreas.hansson@arm.com pkt->dataStatic(data); 1819179Sandreas.hansson@arm.com 1829179Sandreas.hansson@arm.com if (!(memReq->isUncacheable() || memReq->isMmappedIpr())) { 1839179Sandreas.hansson@arm.com // Access memory to see if we have the same data 18410236Sjthestness@gmail.com dcachePort->sendFunctional(pkt); 18510236Sjthestness@gmail.com } else { 18610236Sjthestness@gmail.com // Assume the data is correct if it's an uncached access 1879179Sandreas.hansson@arm.com memcpy(data, unverifiedMemData, size); 1889180Sandreas.hansson@arm.com } 1899179Sandreas.hansson@arm.com 1909179Sandreas.hansson@arm.com delete memReq; 1919179Sandreas.hansson@arm.com memReq = NULL; 1929179Sandreas.hansson@arm.com delete pkt; 1939179Sandreas.hansson@arm.com } 1949179Sandreas.hansson@arm.com 1959179Sandreas.hansson@arm.com if (fault != NoFault) { 1969179Sandreas.hansson@arm.com if (memReq->isPrefetch()) { 19710236Sjthestness@gmail.com fault = NoFault; 19810236Sjthestness@gmail.com } 19910236Sjthestness@gmail.com delete memReq; 20010236Sjthestness@gmail.com memReq = NULL; 2019157Sandreas.hansson@arm.com break; 20210236Sjthestness@gmail.com } 20310236Sjthestness@gmail.com 20410236Sjthestness@gmail.com if (memReq != NULL) { 2059157Sandreas.hansson@arm.com delete memReq; 2069157Sandreas.hansson@arm.com } 2079648Sdam.sunwoo@arm.com 2089157Sandreas.hansson@arm.com //If we don't need to access a second cache line, stop now. 2099793Sakash.bagdia@arm.com if (secondAddr <= addr) 2109793Sakash.bagdia@arm.com { 2119793Sakash.bagdia@arm.com break; 2129793Sakash.bagdia@arm.com } 2139157Sandreas.hansson@arm.com 2149793Sakash.bagdia@arm.com // Setup for accessing next cache line 2159793Sakash.bagdia@arm.com data += size; 2169793Sakash.bagdia@arm.com unverifiedMemData += size; 2179793Sakash.bagdia@arm.com size = addr + fullSize - secondAddr; 2189157Sandreas.hansson@arm.com addr = secondAddr; 2199550Sandreas.hansson@arm.com } 2209987Snilay@cs.wisc.edu 2219157Sandreas.hansson@arm.com if (!flags_match) { 2229157Sandreas.hansson@arm.com warn("%lli: Flags do not match CPU:%#x %#x %#x Checker:%#x %#x %#x\n", 2239157Sandreas.hansson@arm.com curTick(), unverifiedReq->getVaddr(), unverifiedReq->getPaddr(), 2249157Sandreas.hansson@arm.com unverifiedReq->getFlags(), addr, pAddr, flags); 225 handleError(); 226 } 227 228 return fault; 229} 230 231Fault 232CheckerCPU::writeMem(uint8_t *data, unsigned size, 233 Addr addr, unsigned flags, uint64_t *res) 234{ 235 Fault fault = NoFault; 236 bool checked_flags = false; 237 bool flags_match = true; 238 Addr pAddr = 0x0; 239 240 unsigned blockSize = dcachePort->peerBlockSize(); 241 int fullSize = size; 242 243 Addr secondAddr = roundDown(addr + size - 1, blockSize); 244 245 if (secondAddr > addr) 246 size = secondAddr - addr; 247 248 // Need to account for a multiple access like Atomic and Timing CPUs 249 while (1) { 250 memReq = new Request(); 251 memReq->setVirt(0, addr, size, flags, thread->pcState().instAddr()); 252 253 // translate to physical address 254 fault = dtb->translateFunctional(memReq, tc, BaseTLB::Write); 255 256 if (!checked_flags && fault == NoFault && unverifiedReq) { 257 flags_match = checkFlags(unverifiedReq, memReq->getVaddr(), 258 memReq->getPaddr(), memReq->getFlags()); 259 pAddr = memReq->getPaddr(); 260 checked_flags = true; 261 } 262 263 /* 264 * We don't actually check memory for the store because there 265 * is no guarantee it has left the lsq yet, and therefore we 266 * can't verify the memory on stores without lsq snooping 267 * enabled. This is left as future work for the Checker: LSQ snooping 268 * and memory validation after stores have committed. 269 */ 270 271 delete memReq; 272 273 //If we don't need to access a second cache line, stop now. 274 if (fault != NoFault || secondAddr <= addr) 275 { 276 if (fault != NoFault && memReq->isPrefetch()) { 277 fault = NoFault; 278 } 279 break; 280 } 281 282 //Update size and access address 283 size = addr + fullSize - secondAddr; 284 //And access the right address. 285 addr = secondAddr; 286 } 287 288 if (!flags_match) { 289 warn("%lli: Flags do not match CPU:%#x %#x Checker:%#x %#x %#x\n", 290 curTick(), unverifiedReq->getVaddr(), unverifiedReq->getPaddr(), 291 unverifiedReq->getFlags(), addr, pAddr, flags); 292 handleError(); 293 } 294 295 // Assume the result was the same as the one passed in. This checker 296 // doesn't check if the SC should succeed or fail, it just checks the 297 // value. 298 if (unverifiedReq && res && unverifiedReq->extraDataValid()) 299 *res = unverifiedReq->getExtraData(); 300 301 // Entire purpose here is to make sure we are getting the 302 // same data to send to the mem system as the CPU did. 303 // Cannot check this is actually what went to memory because 304 // there stores can be in ld/st queue or coherent operations 305 // overwriting values. 306 bool extraData; 307 if (unverifiedReq) { 308 extraData = unverifiedReq->extraDataValid() ? 309 unverifiedReq->getExtraData() : 1; 310 } 311 312 if (unverifiedReq && unverifiedMemData && 313 memcmp(data, unverifiedMemData, fullSize) && extraData) { 314 warn("%lli: Store value does not match value sent to memory!\ 315 data: %#x inst_data: %#x", curTick(), data, 316 unverifiedMemData); 317 handleError(); 318 } 319 320 return fault; 321} 322 323#if FULL_SYSTEM 324Addr 325CheckerCPU::dbg_vtophys(Addr addr) 326{ 327 return vtophys(tc, addr); 328} 329#endif // FULL_SYSTEM 330 331/** 332 * Checks if the flags set by the Checker and Checkee match. 333 */ 334bool 335CheckerCPU::checkFlags(Request *unverified_req, Addr vAddr, 336 Addr pAddr, int flags) 337{ 338 Addr unverifiedVAddr = unverified_req->getVaddr(); 339 Addr unverifiedPAddr = unverified_req->getPaddr(); 340 int unverifiedFlags = unverified_req->getFlags(); 341 342 if (unverifiedVAddr != vAddr || 343 unverifiedPAddr != pAddr || 344 unverifiedFlags != flags) { 345 return false; 346 } 347 348 return true; 349} 350 351void 352CheckerCPU::dumpAndExit() 353{ 354 warn("%lli: Checker PC:%s", 355 curTick(), thread->pcState()); 356 panic("Checker found an error!"); 357} 358