cpu.cc revision 9814:7ad2b0186a32
11060SN/A/*
22702Sktlim@umich.edu * Copyright (c) 2011,2013 ARM Limited
31060SN/A * All rights reserved
41060SN/A *
51060SN/A * The license below extends only to copyright in the software and shall
61060SN/A * not be construed as granting a license to any other intellectual
71060SN/A * property including but not limited to intellectual property relating
81060SN/A * to a hardware implementation of the functionality of the software
91060SN/A * licensed hereunder.  You may use the software subject to the license
101060SN/A * terms below provided that you ensure that this notice is replicated
111060SN/A * unmodified and in its entirety in all distributions of the software,
121060SN/A * modified or unmodified, in source code or in binary form.
131060SN/A *
141060SN/A * Copyright (c) 2006 The Regents of The University of Michigan
151060SN/A * All rights reserved.
161060SN/A *
171060SN/A * Redistribution and use in source and binary forms, with or without
181060SN/A * modification, are permitted provided that the following conditions are
191060SN/A * met: redistributions of source code must retain the above copyright
201060SN/A * notice, this list of conditions and the following disclaimer;
211060SN/A * redistributions in binary form must reproduce the above copyright
221060SN/A * notice, this list of conditions and the following disclaimer in the
231060SN/A * documentation and/or other materials provided with the distribution;
241060SN/A * neither the name of the copyright holders nor the names of its
251060SN/A * contributors may be used to endorse or promote products derived from
261060SN/A * this software without specific prior written permission.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
291060SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
301060SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
311464SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
321464SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
331060SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
342731Sktlim@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
352292SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
361464SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
371060SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
382669Sktlim@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
391060SN/A *
401060SN/A * Authors: Kevin Lim
411858SN/A *          Geoffrey Blake
426658Snate@binkert.org */
433770Sgblack@eecs.umich.edu
441464SN/A#include <list>
451464SN/A#include <string>
462669Sktlim@umich.edu
471060SN/A#include "arch/kernel_stats.hh"
482669Sktlim@umich.edu#include "arch/vtophys.hh"
492292SN/A#include "cpu/checker/cpu.hh"
506023Snate@binkert.org#include "cpu/base.hh"
511060SN/A#include "cpu/simple_thread.hh"
521060SN/A#include "cpu/static_inst.hh"
531060SN/A#include "cpu/thread_context.hh"
541060SN/A#include "params/CheckerCPU.hh"
551060SN/A#include "sim/full_system.hh"
561060SN/A#include "sim/tlb.hh"
571061SN/A
581061SN/Ausing namespace std;
591060SN/Ausing namespace TheISA;
601060SN/A
611061SN/Avoid
621060SN/ACheckerCPU::init()
631060SN/A{
641060SN/A    masterId = systemPtr->getMasterId(name());
652733Sktlim@umich.edu}
662733Sktlim@umich.edu
671060SN/ACheckerCPU::CheckerCPU(Params *p)
682292SN/A    : BaseCPU(p, true), systemPtr(NULL), icachePort(NULL), dcachePort(NULL),
692107SN/A      tc(NULL), thread(NULL)
702690Sktlim@umich.edu{
712107SN/A    memReq = NULL;
722690Sktlim@umich.edu    curStaticInst = NULL;
732690Sktlim@umich.edu    curMacroStaticInst = NULL;
741060SN/A
752292SN/A    numInst = 0;
762292SN/A    startNumInst = 0;
772292SN/A    numLoad = 0;
782292SN/A    startNumLoad = 0;
792292SN/A    youngestSN = 0;
802292SN/A
811060SN/A    changedPC = willChangePC = changedNextPC = false;
825543Ssaidi@eecs.umich.edu
835543Ssaidi@eecs.umich.edu    exitOnError = p->exitOnError;
841060SN/A    warnOnlyOnLoadError = p->warnOnlyOnLoadError;
851060SN/A    itb = p->itb;
862292SN/A    dtb = p->dtb;
872107SN/A    workload = p->workload;
881060SN/A
891060SN/A    updateOnError = true;
901060SN/A}
911060SN/A
921060SN/ACheckerCPU::~CheckerCPU()
931060SN/A{
942292SN/A}
951060SN/A
961060SN/Avoid
975358Sgblack@eecs.umich.eduCheckerCPU::setSystem(System *system)
985358Sgblack@eecs.umich.edu{
995358Sgblack@eecs.umich.edu    const Params *p(dynamic_cast<const Params *>(_params));
1005358Sgblack@eecs.umich.edu
1015358Sgblack@eecs.umich.edu    systemPtr = system;
1025358Sgblack@eecs.umich.edu
1035358Sgblack@eecs.umich.edu    if (FullSystem) {
1045358Sgblack@eecs.umich.edu        thread = new SimpleThread(this, 0, systemPtr, itb, dtb,
1055358Sgblack@eecs.umich.edu                                  p->isa[0], false);
1065358Sgblack@eecs.umich.edu    } else {
1075358Sgblack@eecs.umich.edu        thread = new SimpleThread(this, 0, systemPtr,
1085358Sgblack@eecs.umich.edu                                  workload.size() ? workload[0] : NULL,
1095358Sgblack@eecs.umich.edu                                  itb, dtb, p->isa[0]);
1102292SN/A    }
1112292SN/A
1122292SN/A    tc = thread->getTC();
1132292SN/A    threadContexts.push_back(tc);
1142292SN/A    thread->kernelStats = NULL;
1152292SN/A    // Thread should never be null after this
1162292SN/A    assert(thread != NULL);
1171060SN/A}
1182132SN/A
1191060SN/Avoid
1202292SN/ACheckerCPU::setIcachePort(MasterPort *icache_port)
1212292SN/A{
1222292SN/A    icachePort = icache_port;
1232292SN/A}
1242292SN/A
1252292SN/Avoid
1262292SN/ACheckerCPU::setDcachePort(MasterPort *dcache_port)
1272292SN/A{
1281060SN/A    dcachePort = dcache_port;
1292132SN/A}
1301060SN/A
1311060SN/Avoid
1321060SN/ACheckerCPU::serialize(ostream &os)
1331060SN/A{
1342132SN/A}
1352132SN/A
1361060SN/Avoid
1371684SN/ACheckerCPU::unserialize(Checkpoint *cp, const string &section)
1381060SN/A{
1391060SN/A}
1401060SN/A
1411060SN/AFault
1422731Sktlim@umich.eduCheckerCPU::readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags)
1432731Sktlim@umich.edu{
1442731Sktlim@umich.edu    Fault fault = NoFault;
1452731Sktlim@umich.edu    int fullSize = size;
1462731Sktlim@umich.edu    Addr secondAddr = roundDown(addr + size - 1, cacheLineSize());
1472731Sktlim@umich.edu    bool checked_flags = false;
1482731Sktlim@umich.edu    bool flags_match = true;
1492731Sktlim@umich.edu    Addr pAddr = 0x0;
1502731Sktlim@umich.edu
1512731Sktlim@umich.edu
1522731Sktlim@umich.edu    if (secondAddr > addr)
1532731Sktlim@umich.edu       size = secondAddr - addr;
1542731Sktlim@umich.edu
1552731Sktlim@umich.edu    // Need to account for multiple accesses like the Atomic and TimingSimple
1562731Sktlim@umich.edu    while (1) {
1572731Sktlim@umich.edu        memReq = new Request();
1582731Sktlim@umich.edu        memReq->setVirt(0, addr, size, flags, masterId, thread->pcState().instAddr());
1592731Sktlim@umich.edu
1602731Sktlim@umich.edu        // translate to physical address
1612731Sktlim@umich.edu        fault = dtb->translateFunctional(memReq, tc, BaseTLB::Read);
1622731Sktlim@umich.edu
1632731Sktlim@umich.edu        if (!checked_flags && fault == NoFault && unverifiedReq) {
1642731Sktlim@umich.edu            flags_match = checkFlags(unverifiedReq, memReq->getVaddr(),
1652731Sktlim@umich.edu                                     memReq->getPaddr(), memReq->getFlags());
1662731Sktlim@umich.edu            pAddr = memReq->getPaddr();
1672292SN/A            checked_flags = true;
1682731Sktlim@umich.edu        }
1692731Sktlim@umich.edu
1701060SN/A        // Now do the access
1711060SN/A        if (fault == NoFault &&
1726221Snate@binkert.org            !memReq->getFlags().isSet(Request::NO_ACCESS)) {
1731060SN/A            PacketPtr pkt = new Packet(memReq,
1741060SN/A                                       memReq->isLLSC() ?
1751060SN/A                                       MemCmd::LoadLockedReq :
1761060SN/A                                       MemCmd::ReadReq);
1772292SN/A
1782292SN/A            pkt->dataStatic(data);
1792292SN/A
1802733Sktlim@umich.edu            if (!(memReq->isUncacheable() || memReq->isMmappedIpr())) {
1812733Sktlim@umich.edu                // Access memory to see if we have the same data
1821060SN/A                dcachePort->sendFunctional(pkt);
1832680Sktlim@umich.edu            } else {
1842292SN/A                // Assume the data is correct if it's an uncached access
1851060SN/A                memcpy(data, unverifiedMemData, size);
1861060SN/A            }
1872132SN/A
1881060SN/A            delete memReq;
1892702Sktlim@umich.edu            memReq = NULL;
1902669Sktlim@umich.edu            delete pkt;
1912292SN/A        }
1921060SN/A
1931060SN/A        if (fault != NoFault) {
1941060SN/A            if (memReq->isPrefetch()) {
1954032Sktlim@umich.edu                fault = NoFault;
1964032Sktlim@umich.edu            }
1974032Sktlim@umich.edu            delete memReq;
1981060SN/A            memReq = NULL;
1991060SN/A            break;
2001060SN/A        }
2011060SN/A
2021060SN/A        if (memReq != NULL) {
2031060SN/A            delete memReq;
2041060SN/A        }
2051060SN/A
2061060SN/A        //If we don't need to access a second cache line, stop now.
2071060SN/A        if (secondAddr <= addr)
2081060SN/A        {
2091060SN/A            break;
2101464SN/A        }
2111464SN/A
2122356SN/A        // Setup for accessing next cache line
2131464SN/A        data += size;
2141464SN/A        unverifiedMemData += size;
2151060SN/A        size = addr + fullSize - secondAddr;
2161464SN/A        addr = secondAddr;
2171464SN/A    }
2181464SN/A
2191464SN/A    if (!flags_match) {
2201060SN/A        warn("%lli: Flags do not match CPU:%#x %#x %#x Checker:%#x %#x %#x\n",
2213326Sktlim@umich.edu             curTick(), unverifiedReq->getVaddr(), unverifiedReq->getPaddr(),
2223326Sktlim@umich.edu             unverifiedReq->getFlags(), addr, pAddr, flags);
2233326Sktlim@umich.edu        handleError();
2241060SN/A    }
2251060SN/A
2261060SN/A    return fault;
2274636Sgblack@eecs.umich.edu}
2284636Sgblack@eecs.umich.edu
2294636Sgblack@eecs.umich.eduFault
2303965Sgblack@eecs.umich.eduCheckerCPU::writeMem(uint8_t *data, unsigned size,
2311060SN/A                     Addr addr, unsigned flags, uint64_t *res)
2321060SN/A{
2331060SN/A    Fault fault = NoFault;
2341060SN/A    bool checked_flags = false;
2351060SN/A    bool flags_match = true;
2361060SN/A    Addr pAddr = 0x0;
2372935Sksewell@umich.edu
2382935Sksewell@umich.edu    int fullSize = size;
2392935Sksewell@umich.edu
2404636Sgblack@eecs.umich.edu    Addr secondAddr = roundDown(addr + size - 1, cacheLineSize());
2414636Sgblack@eecs.umich.edu
2424636Sgblack@eecs.umich.edu    if (secondAddr > addr)
2431060SN/A        size = secondAddr - addr;
2441060SN/A
2451060SN/A    // Need to account for a multiple access like Atomic and Timing CPUs
2463794Sgblack@eecs.umich.edu    while (1) {
2473794Sgblack@eecs.umich.edu        memReq = new Request();
2483794Sgblack@eecs.umich.edu        memReq->setVirt(0, addr, size, flags, masterId, thread->pcState().instAddr());
2494636Sgblack@eecs.umich.edu
2504636Sgblack@eecs.umich.edu        // translate to physical address
2514636Sgblack@eecs.umich.edu        fault = dtb->translateFunctional(memReq, tc, BaseTLB::Write);
2523794Sgblack@eecs.umich.edu
2533794Sgblack@eecs.umich.edu        if (!checked_flags && fault == NoFault && unverifiedReq) {
2543794Sgblack@eecs.umich.edu           flags_match = checkFlags(unverifiedReq, memReq->getVaddr(),
2553965Sgblack@eecs.umich.edu                                    memReq->getPaddr(), memReq->getFlags());
2563965Sgblack@eecs.umich.edu           pAddr = memReq->getPaddr();
2572292SN/A           checked_flags = true;
2582292SN/A        }
2592292SN/A
2602292SN/A        /*
2612292SN/A         * We don't actually check memory for the store because there
2622292SN/A         * is no guarantee it has left the lsq yet, and therefore we
2631060SN/A         * can't verify the memory on stores without lsq snooping
2641060SN/A         * enabled.  This is left as future work for the Checker: LSQ snooping
2651060SN/A         * and memory validation after stores have committed.
2663770Sgblack@eecs.umich.edu         */
2673770Sgblack@eecs.umich.edu        bool was_prefetch = memReq->isPrefetch();
2683770Sgblack@eecs.umich.edu
2693770Sgblack@eecs.umich.edu        delete memReq;
2703770Sgblack@eecs.umich.edu
2713770Sgblack@eecs.umich.edu        //If we don't need to access a second cache line, stop now.
2723770Sgblack@eecs.umich.edu        if (fault != NoFault || secondAddr <= addr)
2733770Sgblack@eecs.umich.edu        {
2743770Sgblack@eecs.umich.edu            if (fault != NoFault && was_prefetch) {
2753770Sgblack@eecs.umich.edu              fault = NoFault;
2763770Sgblack@eecs.umich.edu            }
2773770Sgblack@eecs.umich.edu            break;
2783770Sgblack@eecs.umich.edu        }
2793770Sgblack@eecs.umich.edu
2803770Sgblack@eecs.umich.edu        //Update size and access address
2813770Sgblack@eecs.umich.edu        size = addr + fullSize - secondAddr;
2823770Sgblack@eecs.umich.edu        //And access the right address.
2833770Sgblack@eecs.umich.edu        addr = secondAddr;
2843770Sgblack@eecs.umich.edu   }
2853770Sgblack@eecs.umich.edu
2863770Sgblack@eecs.umich.edu   if (!flags_match) {
2873770Sgblack@eecs.umich.edu       warn("%lli: Flags do not match CPU:%#x %#x Checker:%#x %#x %#x\n",
2883770Sgblack@eecs.umich.edu            curTick(), unverifiedReq->getVaddr(), unverifiedReq->getPaddr(),
2893770Sgblack@eecs.umich.edu            unverifiedReq->getFlags(), addr, pAddr, flags);
2903770Sgblack@eecs.umich.edu       handleError();
2913770Sgblack@eecs.umich.edu   }
2921060SN/A
2933770Sgblack@eecs.umich.edu   // Assume the result was the same as the one passed in.  This checker
2943770Sgblack@eecs.umich.edu   // doesn't check if the SC should succeed or fail, it just checks the
2953770Sgblack@eecs.umich.edu   // value.
2963770Sgblack@eecs.umich.edu   if (unverifiedReq && res && unverifiedReq->extraDataValid())
2973770Sgblack@eecs.umich.edu       *res = unverifiedReq->getExtraData();
2983770Sgblack@eecs.umich.edu
2993770Sgblack@eecs.umich.edu   // Entire purpose here is to make sure we are getting the
3003770Sgblack@eecs.umich.edu   // same data to send to the mem system as the CPU did.
3013770Sgblack@eecs.umich.edu   // Cannot check this is actually what went to memory because
3023770Sgblack@eecs.umich.edu   // there stores can be in ld/st queue or coherent operations
3033770Sgblack@eecs.umich.edu   // overwriting values.
3043770Sgblack@eecs.umich.edu   bool extraData;
3053770Sgblack@eecs.umich.edu   if (unverifiedReq) {
3063770Sgblack@eecs.umich.edu       extraData = unverifiedReq->extraDataValid() ?
3073770Sgblack@eecs.umich.edu                        unverifiedReq->getExtraData() : 1;
3083770Sgblack@eecs.umich.edu   }
3093770Sgblack@eecs.umich.edu
3103770Sgblack@eecs.umich.edu   if (unverifiedReq && unverifiedMemData &&
3113770Sgblack@eecs.umich.edu       memcmp(data, unverifiedMemData, fullSize) && extraData) {
3123770Sgblack@eecs.umich.edu           warn("%lli: Store value does not match value sent to memory!\
3133770Sgblack@eecs.umich.edu                  data: %#x inst_data: %#x", curTick(), data,
3143770Sgblack@eecs.umich.edu                  unverifiedMemData);
3153770Sgblack@eecs.umich.edu       handleError();
3163770Sgblack@eecs.umich.edu   }
3173770Sgblack@eecs.umich.edu
3183770Sgblack@eecs.umich.edu   return fault;
3193770Sgblack@eecs.umich.edu}
3203770Sgblack@eecs.umich.edu
3213770Sgblack@eecs.umich.eduAddr
3223770Sgblack@eecs.umich.eduCheckerCPU::dbg_vtophys(Addr addr)
3233770Sgblack@eecs.umich.edu{
3243770Sgblack@eecs.umich.edu    return vtophys(tc, addr);
3253770Sgblack@eecs.umich.edu}
3263770Sgblack@eecs.umich.edu
3273770Sgblack@eecs.umich.edu/**
3283770Sgblack@eecs.umich.edu * Checks if the flags set by the Checker and Checkee match.
3293770Sgblack@eecs.umich.edu */
3303770Sgblack@eecs.umich.edubool
3313770Sgblack@eecs.umich.eduCheckerCPU::checkFlags(Request *unverified_req, Addr vAddr,
3323770Sgblack@eecs.umich.edu                       Addr pAddr, int flags)
3333770Sgblack@eecs.umich.edu{
3343770Sgblack@eecs.umich.edu    Addr unverifiedVAddr = unverified_req->getVaddr();
3353770Sgblack@eecs.umich.edu    Addr unverifiedPAddr = unverified_req->getPaddr();
3363770Sgblack@eecs.umich.edu    int unverifiedFlags = unverified_req->getFlags();
3373770Sgblack@eecs.umich.edu
3383770Sgblack@eecs.umich.edu    if (unverifiedVAddr != vAddr ||
3393770Sgblack@eecs.umich.edu        unverifiedPAddr != pAddr ||
3403770Sgblack@eecs.umich.edu        unverifiedFlags != flags) {
3413770Sgblack@eecs.umich.edu        return false;
3423770Sgblack@eecs.umich.edu    }
3433770Sgblack@eecs.umich.edu
3443770Sgblack@eecs.umich.edu    return true;
3453770Sgblack@eecs.umich.edu}
3463770Sgblack@eecs.umich.edu
3473770Sgblack@eecs.umich.eduvoid
3483770Sgblack@eecs.umich.eduCheckerCPU::dumpAndExit()
3493770Sgblack@eecs.umich.edu{
3503770Sgblack@eecs.umich.edu    warn("%lli: Checker PC:%s",
3513770Sgblack@eecs.umich.edu         curTick(), thread->pcState());
3523770Sgblack@eecs.umich.edu    panic("Checker found an error!");
3533770Sgblack@eecs.umich.edu}
3543770Sgblack@eecs.umich.edu