cpu.cc revision 3565
1/* 2 * Copyright (c) 2006 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Kevin Lim 29 */ 30 31#include <list> 32#include <string> 33 34#include "cpu/base.hh" 35#include "cpu/checker/cpu.hh" 36#include "cpu/simple_thread.hh" 37#include "cpu/static_inst.hh" 38#include "cpu/thread_context.hh" 39 40#if FULL_SYSTEM 41#include "arch/kernel_stats.hh" 42#include "arch/vtophys.hh" 43#endif // FULL_SYSTEM 44 45using namespace std; 46//The CheckerCPU does alpha only 47using namespace AlphaISA; 48 49void 50CheckerCPU::init() 51{ 52} 53 54CheckerCPU::CheckerCPU(Params *p) 55 : BaseCPU(p), thread(NULL), tc(NULL) 56{ 57 memReq = NULL; 58 59 numInst = 0; 60 startNumInst = 0; 61 numLoad = 0; 62 startNumLoad = 0; 63 youngestSN = 0; 64 65 changedPC = willChangePC = changedNextPC = false; 66 67 exitOnError = p->exitOnError; 68 warnOnlyOnLoadError = p->warnOnlyOnLoadError; 69#if FULL_SYSTEM 70 itb = p->itb; 71 dtb = p->dtb; 72 systemPtr = NULL; 73#else 74 process = p->process; 75 thread = new SimpleThread(this, /* thread_num */ 0, process, 76 /* asid */ 0); 77 78 thread->setStatus(ThreadContext::Suspended); 79 tc = thread->getTC(); 80 threadContexts.push_back(tc); 81#endif 82 83 result.integer = 0; 84} 85 86CheckerCPU::~CheckerCPU() 87{ 88} 89 90void 91CheckerCPU::setSystem(System *system) 92{ 93#if FULL_SYSTEM 94 systemPtr = system; 95 96 thread = new SimpleThread(this, 0, systemPtr, itb, dtb, false); 97 98 thread->setStatus(ThreadContext::Suspended); 99 tc = thread->getTC(); 100 threadContexts.push_back(tc); 101 delete thread->kernelStats; 102 thread->kernelStats = NULL; 103#endif 104} 105 106void 107CheckerCPU::setIcachePort(Port *icache_port) 108{ 109 icachePort = icache_port; 110} 111 112void 113CheckerCPU::setDcachePort(Port *dcache_port) 114{ 115 dcachePort = dcache_port; 116} 117 118void 119CheckerCPU::serialize(ostream &os) 120{ 121/* 122 BaseCPU::serialize(os); 123 SERIALIZE_SCALAR(inst); 124 nameOut(os, csprintf("%s.xc", name())); 125 thread->serialize(os); 126 cacheCompletionEvent.serialize(os); 127*/ 128} 129 130void 131CheckerCPU::unserialize(Checkpoint *cp, const string §ion) 132{ 133/* 134 BaseCPU::unserialize(cp, section); 135 UNSERIALIZE_SCALAR(inst); 136 thread->unserialize(cp, csprintf("%s.xc", section)); 137*/ 138} 139 140Fault 141CheckerCPU::copySrcTranslate(Addr src) 142{ 143 panic("Unimplemented!"); 144} 145 146Fault 147CheckerCPU::copy(Addr dest) 148{ 149 panic("Unimplemented!"); 150} 151 152template <class T> 153Fault 154CheckerCPU::read(Addr addr, T &data, unsigned flags) 155{ 156 // need to fill in CPU & thread IDs here 157 memReq = new Request(); 158 159 memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); 160 161 // translate to physical address 162 translateDataReadReq(memReq); 163 164 PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); 165 166 pkt->dataStatic(&data); 167 168 if (!(memReq->isUncacheable())) { 169 // Access memory to see if we have the same data 170 dcachePort->sendFunctional(pkt); 171 } else { 172 // Assume the data is correct if it's an uncached access 173 memcpy(&data, &unverifiedResult.integer, sizeof(T)); 174 } 175 176 delete pkt; 177 178 return NoFault; 179} 180 181#ifndef DOXYGEN_SHOULD_SKIP_THIS 182 183template 184Fault 185CheckerCPU::read(Addr addr, uint64_t &data, unsigned flags); 186 187template 188Fault 189CheckerCPU::read(Addr addr, uint32_t &data, unsigned flags); 190 191template 192Fault 193CheckerCPU::read(Addr addr, uint16_t &data, unsigned flags); 194 195template 196Fault 197CheckerCPU::read(Addr addr, uint8_t &data, unsigned flags); 198 199#endif //DOXYGEN_SHOULD_SKIP_THIS 200 201template<> 202Fault 203CheckerCPU::read(Addr addr, double &data, unsigned flags) 204{ 205 return read(addr, *(uint64_t*)&data, flags); 206} 207 208template<> 209Fault 210CheckerCPU::read(Addr addr, float &data, unsigned flags) 211{ 212 return read(addr, *(uint32_t*)&data, flags); 213} 214 215template<> 216Fault 217CheckerCPU::read(Addr addr, int32_t &data, unsigned flags) 218{ 219 return read(addr, (uint32_t&)data, flags); 220} 221 222template <class T> 223Fault 224CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) 225{ 226 // need to fill in CPU & thread IDs here 227 memReq = new Request(); 228 229 memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); 230 231 // translate to physical address 232 thread->translateDataWriteReq(memReq); 233 234 // Can compare the write data and result only if it's cacheable, 235 // not a store conditional, or is a store conditional that 236 // succeeded. 237 // @todo: Verify that actual memory matches up with these values. 238 // Right now it only verifies that the instruction data is the 239 // same as what was in the request that got sent to memory; there 240 // is no verification that it is the same as what is in memory. 241 // This is because the LSQ would have to be snooped in the CPU to 242 // verify this data. 243 if (unverifiedReq && 244 !(unverifiedReq->isUncacheable()) && 245 (!(unverifiedReq->isLocked()) || 246 ((unverifiedReq->isLocked()) && 247 unverifiedReq->getScResult() == 1))) { 248 T inst_data; 249/* 250 // This code would work if the LSQ allowed for snooping. 251 PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); 252 pkt.dataStatic(&inst_data); 253 254 dcachePort->sendFunctional(pkt); 255 256 delete pkt; 257*/ 258 memcpy(&inst_data, unverifiedMemData, sizeof(T)); 259 260 if (data != inst_data) { 261 warn("%lli: Store value does not match value in memory! " 262 "Instruction: %#x, memory: %#x", 263 curTick, inst_data, data); 264 handleError(); 265 } 266 } 267 268 // Assume the result was the same as the one passed in. This checker 269 // doesn't check if the SC should succeed or fail, it just checks the 270 // value. 271 if (res && unverifiedReq->scResultValid()) 272 *res = unverifiedReq->getScResult(); 273 274 return NoFault; 275} 276 277 278#ifndef DOXYGEN_SHOULD_SKIP_THIS 279template 280Fault 281CheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res); 282 283template 284Fault 285CheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res); 286 287template 288Fault 289CheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res); 290 291template 292Fault 293CheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res); 294 295#endif //DOXYGEN_SHOULD_SKIP_THIS 296 297template<> 298Fault 299CheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res) 300{ 301 return write(*(uint64_t*)&data, addr, flags, res); 302} 303 304template<> 305Fault 306CheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res) 307{ 308 return write(*(uint32_t*)&data, addr, flags, res); 309} 310 311template<> 312Fault 313CheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) 314{ 315 return write((uint32_t)data, addr, flags, res); 316} 317 318 319#if FULL_SYSTEM 320Addr 321CheckerCPU::dbg_vtophys(Addr addr) 322{ 323 return vtophys(tc, addr); 324} 325#endif // FULL_SYSTEM 326 327bool 328CheckerCPU::translateInstReq(Request *req) 329{ 330#if FULL_SYSTEM 331 return (thread->translateInstReq(req) == NoFault); 332#else 333 thread->translateInstReq(req); 334 return true; 335#endif 336} 337 338void 339CheckerCPU::translateDataReadReq(Request *req) 340{ 341 thread->translateDataReadReq(req); 342 343 if (req->getVaddr() != unverifiedReq->getVaddr()) { 344 warn("%lli: Request virtual addresses do not match! Inst: %#x, " 345 "checker: %#x", 346 curTick, unverifiedReq->getVaddr(), req->getVaddr()); 347 handleError(); 348 } 349 req->setPaddr(unverifiedReq->getPaddr()); 350 351 if (checkFlags(req)) { 352 warn("%lli: Request flags do not match! Inst: %#x, checker: %#x", 353 curTick, unverifiedReq->getFlags(), req->getFlags()); 354 handleError(); 355 } 356} 357 358void 359CheckerCPU::translateDataWriteReq(Request *req) 360{ 361 thread->translateDataWriteReq(req); 362 363 if (req->getVaddr() != unverifiedReq->getVaddr()) { 364 warn("%lli: Request virtual addresses do not match! Inst: %#x, " 365 "checker: %#x", 366 curTick, unverifiedReq->getVaddr(), req->getVaddr()); 367 handleError(); 368 } 369 req->setPaddr(unverifiedReq->getPaddr()); 370 371 if (checkFlags(req)) { 372 warn("%lli: Request flags do not match! Inst: %#x, checker: %#x", 373 curTick, unverifiedReq->getFlags(), req->getFlags()); 374 handleError(); 375 } 376} 377 378bool 379CheckerCPU::checkFlags(Request *req) 380{ 381 // Remove any dynamic flags that don't have to do with the request itself. 382 unsigned flags = unverifiedReq->getFlags(); 383 unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | NO_FAULT; 384 flags = flags & (mask); 385 if (flags == req->getFlags()) { 386 return false; 387 } else { 388 return true; 389 } 390} 391 392void 393CheckerCPU::dumpAndExit() 394{ 395 warn("%lli: Checker PC:%#x, next PC:%#x", 396 curTick, thread->readPC(), thread->readNextPC()); 397 panic("Checker found an error!"); 398} 399