From af6aaf258171027af8d3cf0ef86dddff501a3ccb Mon Sep 17 00:00:00 2001 From: Geoffrey Blake Date: Tue, 31 Jan 2012 07:46:03 -0800 Subject: CheckerCPU: Re-factor CheckerCPU to be compatible with current gem5 Brings the CheckerCPU back to life to allow FS and SE checking of the O3CPU. These changes have only been tested with the ARM ISA. Other ISAs potentially require modification. --- src/arch/arm/isa.cc | 53 +++++++++++++++++++++++++++++++++++++++- src/arch/arm/isa/insts/m5ops.isa | 4 +-- src/arch/arm/isa/insts/misc.isa | 8 +++--- src/arch/arm/table_walker.cc | 25 ++++++++++++++++--- src/arch/arm/table_walker.hh | 5 +++- src/arch/arm/tlb.cc | 21 ++++++++++++++-- src/arch/arm/tlb.hh | 9 ++++++- src/arch/arm/utility.cc | 5 ++++ 8 files changed, 117 insertions(+), 13 deletions(-) (limited to 'src/arch') diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc index b504550a1..5c2478946 100644 --- a/src/arch/arm/isa.cc +++ b/src/arch/arm/isa.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 ARM Limited + * Copyright (c) 2010-2011 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -39,12 +39,17 @@ */ #include "arch/arm/isa.hh" +#include "config/use_checker.hh" #include "debug/Arm.hh" #include "debug/MiscRegs.hh" #include "sim/faults.hh" #include "sim/stat_control.hh" #include "sim/system.hh" +#if USE_CHECKER +#include "cpu/checker/cpu.hh" +#endif + namespace ArmISA { @@ -279,7 +284,11 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) PCState pc = tc->pcState(); pc.nextThumb(cpsr.t); pc.nextJazelle(cpsr.j); +#if USE_CHECKER + tc->pcStateNoRecord(pc); +#else tc->pcState(pc); +#endif //USE_CHECKER } else if (misc_reg >= MISCREG_CP15_UNIMP_START && misc_reg < MISCREG_CP15_END) { panic("Unimplemented CP15 register %s wrote with %#x.\n", @@ -382,6 +391,14 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) oc = sys->getThreadContext(x); oc->getDTBPtr()->allCpusCaching(); oc->getITBPtr()->allCpusCaching(); +#if USE_CHECKER + CheckerCPU *checker = + dynamic_cast(oc->getCheckerCpuPtr()); + if (checker) { + checker->getDTBPtr()->allCpusCaching(); + checker->getITBPtr()->allCpusCaching(); + } +#endif } return; } @@ -399,6 +416,14 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) assert(oc->getITBPtr() && oc->getDTBPtr()); oc->getITBPtr()->flushAll(); oc->getDTBPtr()->flushAll(); +#if USE_CHECKER + CheckerCPU *checker = + dynamic_cast(oc->getCheckerCpuPtr()); + if (checker) { + checker->getITBPtr()->flushAll(); + checker->getDTBPtr()->flushAll(); + } +#endif } return; case MISCREG_ITLBIALL: @@ -417,6 +442,16 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) bits(newVal, 7,0)); oc->getDTBPtr()->flushMvaAsid(mbits(newVal, 31, 12), bits(newVal, 7,0)); +#if USE_CHECKER + CheckerCPU *checker = + dynamic_cast(oc->getCheckerCpuPtr()); + if (checker) { + checker->getITBPtr()->flushMvaAsid(mbits(newVal, 31, 12), + bits(newVal, 7,0)); + checker->getDTBPtr()->flushMvaAsid(mbits(newVal, 31, 12), + bits(newVal, 7,0)); + } +#endif } return; case MISCREG_TLBIASIDIS: @@ -427,6 +462,14 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) assert(oc->getITBPtr() && oc->getDTBPtr()); oc->getITBPtr()->flushAsid(bits(newVal, 7,0)); oc->getDTBPtr()->flushAsid(bits(newVal, 7,0)); +#if USE_CHECKER + CheckerCPU *checker = + dynamic_cast(oc->getCheckerCpuPtr()); + if (checker) { + checker->getITBPtr()->flushAsid(bits(newVal, 7,0)); + checker->getDTBPtr()->flushAsid(bits(newVal, 7,0)); + } +#endif } return; case MISCREG_TLBIMVAAIS: @@ -437,6 +480,14 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) assert(oc->getITBPtr() && oc->getDTBPtr()); oc->getITBPtr()->flushMva(mbits(newVal, 31,12)); oc->getDTBPtr()->flushMva(mbits(newVal, 31,12)); +#if USE_CHECKER + CheckerCPU *checker = + dynamic_cast(oc->getCheckerCpuPtr()); + if (checker) { + checker->getITBPtr()->flushMva(mbits(newVal, 31,12)); + checker->getDTBPtr()->flushMva(mbits(newVal, 31,12)); + } +#endif } return; case MISCREG_ITLBIMVA: diff --git a/src/arch/arm/isa/insts/m5ops.isa b/src/arch/arm/isa/insts/m5ops.isa index f20908d4f..222ecc647 100644 --- a/src/arch/arm/isa/insts/m5ops.isa +++ b/src/arch/arm/isa/insts/m5ops.isa @@ -247,7 +247,7 @@ let {{ m5checkpointIop = InstObjParams("m5checkpoint", "M5checkpoint", "PredOp", { "code": m5checkpoint_code, "predicate_test": predicateTest }, - ["IsNonSpeculative"]) + ["IsNonSpeculative", "IsUnverifiable"]) header_output += BasicDeclare.subst(m5checkpointIop) decoder_output += BasicConstructor.subst(m5checkpointIop) exec_output += PredOpExecute.subst(m5checkpointIop) @@ -260,7 +260,7 @@ let {{ m5readfileIop = InstObjParams("m5readfile", "M5readfile", "PredOp", { "code": m5readfileCode, "predicate_test": predicateTest }, - ["IsNonSpeculative"]) + ["IsNonSpeculative", "IsUnverifiable"]) header_output += BasicDeclare.subst(m5readfileIop) decoder_output += BasicConstructor.subst(m5readfileIop) exec_output += PredOpExecute.subst(m5readfileIop) diff --git a/src/arch/arm/isa/insts/misc.isa b/src/arch/arm/isa/insts/misc.isa index 870f037d0..45d5d8d32 100644 --- a/src/arch/arm/isa/insts/misc.isa +++ b/src/arch/arm/isa/insts/misc.isa @@ -525,7 +525,8 @@ let {{ { "code" : wfeCode, "pred_fixup" : wfePredFixUpCode, "predicate_test" : predicateTest }, - ["IsNonSpeculative", "IsQuiesce", "IsSerializeAfter"]) + ["IsNonSpeculative", "IsQuiesce", + "IsSerializeAfter", "IsUnverifiable"]) header_output += BasicDeclare.subst(wfeIop) decoder_output += BasicConstructor.subst(wfeIop) exec_output += QuiescePredOpExecuteWithFixup.subst(wfeIop) @@ -542,7 +543,8 @@ let {{ ''' wfiIop = InstObjParams("wfi", "WfiInst", "PredOp", \ { "code" : wfiCode, "predicate_test" : predicateTest }, - ["IsNonSpeculative", "IsQuiesce", "IsSerializeAfter"]) + ["IsNonSpeculative", "IsQuiesce", + "IsSerializeAfter", "IsUnverifiable"]) header_output += BasicDeclare.subst(wfiIop) decoder_output += BasicConstructor.subst(wfiIop) exec_output += QuiescePredOpExecute.subst(wfiIop) @@ -565,7 +567,7 @@ let {{ ''' sevIop = InstObjParams("sev", "SevInst", "PredOp", \ { "code" : sevCode, "predicate_test" : predicateTest }, - ["IsNonSpeculative", "IsSquashAfter"]) + ["IsNonSpeculative", "IsSquashAfter", "IsUnverifiable"]) header_output += BasicDeclare.subst(sevIop) decoder_output += BasicConstructor.subst(sevIop) exec_output += PredOpExecute.subst(sevIop) diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc index b2ab010c0..9c92ebdf6 100644 --- a/src/arch/arm/table_walker.cc +++ b/src/arch/arm/table_walker.cc @@ -107,8 +107,9 @@ TableWalker::getPort(const std::string &if_name, int idx) Fault TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode _mode, - TLB::Translation *_trans, bool _timing) + TLB::Translation *_trans, bool _timing, bool _functional) { + assert(!(_functional && _timing)); if (!currState) { // For atomic mode, a new WalkerState instance should be only created // once per TLB. For timing mode, a new instance is generated for every @@ -136,6 +137,7 @@ TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode _ currState->fault = NoFault; currState->contextId = _cid; currState->timing = _timing; + currState->functional = _functional; currState->mode = _mode; /** @todo These should be cached or grabbed from cached copies in @@ -230,12 +232,21 @@ TableWalker::processWalk() stateQueueL1.size()); stateQueueL1.push_back(currState); currState = NULL; - } else { + } else if (!currState->functional) { port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t), NULL, (uint8_t*)&currState->l1Desc.data, currState->tc->getCpuPtr()->ticks(1), flag); doL1Descriptor(); f = currState->fault; + } else { + RequestPtr req = new Request(l1desc_addr, sizeof(uint32_t), flag); + PacketPtr pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast); + pkt->dataStatic((uint8_t*)&currState->l1Desc.data); + port->sendFunctional(pkt); + doL1Descriptor(); + delete req; + delete pkt; + f = currState->fault; } return f; @@ -566,11 +577,19 @@ TableWalker::doL1Descriptor() port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t), &doL2DescEvent, (uint8_t*)&currState->l2Desc.data, currState->tc->getCpuPtr()->ticks(1)); - } else { + } else if (!currState->functional) { port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t), NULL, (uint8_t*)&currState->l2Desc.data, currState->tc->getCpuPtr()->ticks(1)); doL2Descriptor(); + } else { + RequestPtr req = new Request(l2desc_addr, sizeof(uint32_t), 0); + PacketPtr pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast); + pkt->dataStatic((uint8_t*)&currState->l2Desc.data); + port->sendFunctional(pkt); + doL2Descriptor(); + delete req; + delete pkt; } return; default: diff --git a/src/arch/arm/table_walker.hh b/src/arch/arm/table_walker.hh index 85db1fa77..d4a2e87b5 100644 --- a/src/arch/arm/table_walker.hh +++ b/src/arch/arm/table_walker.hh @@ -294,6 +294,9 @@ class TableWalker : public MemObject /** If the mode is timing or atomic */ bool timing; + /** If the atomic mode should be functional */ + bool functional; + /** Save mode for use in delayed response */ BaseTLB::Mode mode; @@ -354,7 +357,7 @@ class TableWalker : public MemObject virtual Port *getPort(const std::string &if_name, int idx = -1); Fault walk(RequestPtr req, ThreadContext *tc, uint8_t cid, TLB::Mode mode, - TLB::Translation *_trans, bool timing); + TLB::Translation *_trans, bool timing, bool functional = false); void setTlb(TLB *_tlb) { tlb = _tlb; } void memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr, diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc index a03e445cf..f4dc47655 100644 --- a/src/arch/arm/tlb.cc +++ b/src/arch/arm/tlb.cc @@ -453,8 +453,11 @@ TLB::walkTrickBoxCheck(Addr pa, Addr va, Addr sz, bool is_exec, Fault TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode, - Translation *translation, bool &delay, bool timing) + Translation *translation, bool &delay, bool timing, bool functional) { + // No such thing as a functional timing access + assert(!(timing && functional)); + if (!miscRegValid) { updateMiscReg(tc); DPRINTF(TLBVerbose, "TLB variables changed!\n"); @@ -541,7 +544,7 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode, DPRINTF(TLB, "TLB Miss: Starting hardware table walker for %#x(%d)\n", vaddr, contextId); fault = tableWalker->walk(req, tc, contextId, mode, translation, - timing); + timing, functional); if (timing && fault == NoFault) { delay = true; // for timing mode, return and wait for table walk @@ -700,6 +703,20 @@ TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode) return fault; } +Fault +TLB::translateFunctional(RequestPtr req, ThreadContext *tc, Mode mode) +{ + bool delay = false; + Fault fault; +#if FULL_SYSTEM + fault = translateFs(req, tc, mode, NULL, delay, false, true); +#else + fault = translateSe(req, tc, mode, NULL, delay, false); +#endif + assert(!delay); + return fault; +} + Fault TLB::translateTiming(RequestPtr req, ThreadContext *tc, Translation *translation, Mode mode) diff --git a/src/arch/arm/tlb.hh b/src/arch/arm/tlb.hh index 3464e42b3..bdfa2fc9f 100644 --- a/src/arch/arm/tlb.hh +++ b/src/arch/arm/tlb.hh @@ -182,6 +182,12 @@ class TLB : public BaseTLB */ bool translateFunctional(ThreadContext *tc, Addr vaddr, Addr &paddr); + /** + * Do a functional lookup on the TLB (for checker cpu) that + * behaves like a normal lookup without modifying any page table state. + */ + Fault translateFunctional(RequestPtr req, ThreadContext *tc, Mode mode); + /** Accessor functions for memory attributes for last accessed TLB entry */ void @@ -197,7 +203,8 @@ class TLB : public BaseTLB #if FULL_SYSTEM Fault translateFs(RequestPtr req, ThreadContext *tc, Mode mode, - Translation *translation, bool &delay, bool timing); + Translation *translation, bool &delay, + bool timing, bool functional = false); #else Fault translateSe(RequestPtr req, ThreadContext *tc, Mode mode, Translation *translation, bool &delay, bool timing); diff --git a/src/arch/arm/utility.cc b/src/arch/arm/utility.cc index 98195ab04..b31dc4324 100644 --- a/src/arch/arm/utility.cc +++ b/src/arch/arm/utility.cc @@ -41,6 +41,7 @@ #include "arch/arm/faults.hh" #include "arch/arm/isa_traits.hh" #include "arch/arm/utility.hh" +#include "config/use_checker.hh" #include "cpu/thread_context.hh" #if FULL_SYSTEM @@ -116,7 +117,11 @@ skipFunction(ThreadContext *tc) { TheISA::PCState newPC = tc->pcState(); newPC.set(tc->readIntReg(ReturnAddressReg) & ~ULL(1)); +#if USE_CHECKER + tc->pcStateNoRecord(newPC); +#else tc->pcState(newPC); +#endif } void -- cgit v1.2.3