summaryrefslogtreecommitdiff
path: root/src/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/arm')
-rw-r--r--src/arch/arm/isa.cc53
-rw-r--r--src/arch/arm/isa/insts/m5ops.isa4
-rw-r--r--src/arch/arm/isa/insts/misc.isa8
-rw-r--r--src/arch/arm/table_walker.cc25
-rw-r--r--src/arch/arm/table_walker.hh5
-rw-r--r--src/arch/arm/tlb.cc21
-rw-r--r--src/arch/arm/tlb.hh9
-rw-r--r--src/arch/arm/utility.cc5
8 files changed, 117 insertions, 13 deletions
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<CheckerCPU*>(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<CheckerCPU*>(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<CheckerCPU*>(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<CheckerCPU*>(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<CheckerCPU*>(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
@@ -701,6 +704,20 @@ TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode)
}
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