summaryrefslogtreecommitdiff
path: root/src/arch/arm
diff options
context:
space:
mode:
authorAli Saidi <Ali.Saidi@ARM.com>2010-11-15 14:04:03 -0600
committerAli Saidi <Ali.Saidi@ARM.com>2010-11-15 14:04:03 -0600
commit13931b9b827abd8a9fba5cb4448b69066746637c (patch)
tree348231f50e7e0fd224fdf255b3c0a2159097750f /src/arch/arm
parent4c2e5c282b334dcd263373c48d325c7f77847c61 (diff)
downloadgem5-13931b9b827abd8a9fba5cb4448b69066746637c.tar.xz
ARM: Cache the misc regs at the TLB to limit readMiscReg() calls.
Diffstat (limited to 'src/arch/arm')
-rw-r--r--src/arch/arm/isa.cc20
-rw-r--r--src/arch/arm/tlb.cc41
-rw-r--r--src/arch/arm/tlb.hh26
-rw-r--r--src/arch/arm/utility.cc8
4 files changed, 72 insertions, 23 deletions
diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc
index 20cddcff1..67062be41 100644
--- a/src/arch/arm/isa.cc
+++ b/src/arch/arm/isa.cc
@@ -227,10 +227,20 @@ ISA::setMiscRegNoEffect(int misc_reg, const MiscReg &val)
void
ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
{
+
MiscReg newVal = val;
if (misc_reg == MISCREG_CPSR) {
updateRegMap(val);
+
+
+ CPSR old_cpsr = miscRegs[MISCREG_CPSR];
+ int old_mode = old_cpsr.mode;
CPSR cpsr = val;
+ if (old_mode != cpsr.mode) {
+ tc->getITBPtr()->invalidateMiscReg();
+ tc->getDTBPtr()->invalidateMiscReg();
+ }
+
DPRINTF(Arm, "Updating CPSR from %#x to %#x f:%d i:%d a:%d mode:%#x\n",
miscRegs[misc_reg], cpsr, cpsr.f, cpsr.i, cpsr.a, cpsr.mode);
PCState pc = tc->pcState();
@@ -309,6 +319,8 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
SCTLR new_sctlr = newVal;
new_sctlr.nmfi = (bool)sctlr.nmfi;
miscRegs[MISCREG_SCTLR] = (MiscReg)new_sctlr;
+ tc->getITBPtr()->invalidateMiscReg();
+ tc->getDTBPtr()->invalidateMiscReg();
return;
}
case MISCREG_TLBTR:
@@ -426,6 +438,14 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
}
return;
}
+ case MISCREG_CONTEXTIDR:
+ case MISCREG_PRRR:
+ case MISCREG_NMRR:
+ case MISCREG_DACR:
+ tc->getITBPtr()->invalidateMiscReg();
+ tc->getDTBPtr()->invalidateMiscReg();
+ break;
+
}
}
setMiscRegNoEffect(misc_reg, newVal);
diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc
index 53509372a..6d6da15c8 100644
--- a/src/arch/arm/tlb.cc
+++ b/src/arch/arm/tlb.cc
@@ -69,7 +69,7 @@ TLB::TLB(const Params *p)
#if FULL_SYSTEM
, tableWalker(p->walker)
#endif
- , rangeMRU(1)
+ , rangeMRU(1), miscRegValid(false)
{
table = new TlbEntry[size];
memset(table, 0, sizeof(TlbEntry[size]));
@@ -88,8 +88,9 @@ TLB::~TLB()
bool
TLB::translateFunctional(ThreadContext *tc, Addr va, Addr &pa)
{
- uint32_t context_id = tc->readMiscReg(MISCREG_CONTEXTIDR);
- TlbEntry *e = lookup(va, context_id, true);
+ if (!miscRegValid)
+ updateMiscReg(tc);
+ TlbEntry *e = lookup(va, contextId, true);
if (!e)
return false;
pa = e->pAddr(va);
@@ -275,6 +276,7 @@ TLB::unserialize(Checkpoint *cp, const string &section)
for(int i = 0; i < size; i++){
table[i].unserialize(cp, csprintf("%s.TlbEntry%d", section, i));
}
+ miscRegValid = false;
}
void
@@ -398,9 +400,9 @@ Fault
TLB::translateSe(RequestPtr req, ThreadContext *tc, Mode mode,
Translation *translation, bool &delay, bool timing)
{
- // XXX Cache misc registers and have miscreg write function inv cache
+ if (!miscRegValid)
+ updateMiscReg(tc);
Addr vaddr = req->getVaddr();
- SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
uint32_t flags = req->getFlags();
bool is_fetch = (mode == Execute);
@@ -444,18 +446,18 @@ Fault
TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
Translation *translation, bool &delay, bool timing)
{
- // XXX Cache misc registers and have miscreg write function inv cache
+ if (!miscRegValid)
+ updateMiscReg(tc);
+
Addr vaddr = req->getVaddr();
- SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
- CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
uint32_t flags = req->getFlags();
bool is_fetch = (mode == Execute);
bool is_write = (mode == Write);
- bool is_priv = (cpsr.mode != MODE_USER) && !(flags & UserMode);
+ bool is_priv = isPriv && !(flags & UserMode);
- DPRINTF(TLBVerbose, "CPSR is user:%d UserMode:%d\n", cpsr.mode == MODE_USER, flags
- & UserMode);
+ DPRINTF(TLBVerbose, "CPSR is user:%d UserMode:%d\n",
+ isPriv, flags & UserMode);
// If this is a clrex instruction, provide a PA of 0 with no fault
// This will force the monitor to set the tracked address to 0
// a bit of a hack but this effectively clrears this processors monitor
@@ -479,18 +481,13 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
}
}
- uint32_t context_id = tc->readMiscReg(MISCREG_CONTEXTIDR);
Fault fault;
-
if (!sctlr.m) {
req->setPaddr(vaddr);
if (sctlr.tre == 0) {
req->setFlags(Request::UNCACHEABLE);
} else {
- PRRR prrr = tc->readMiscReg(MISCREG_PRRR);
- NMRR nmrr = tc->readMiscReg(MISCREG_NMRR);
-
if (nmrr.ir0 == 0 || nmrr.or0 == 0 || prrr.tr0 != 0x2)
req->setFlags(Request::UNCACHEABLE);
}
@@ -507,10 +504,10 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
return trickBoxCheck(req, mode, 0, false);
}
- DPRINTF(TLBVerbose, "Translating vaddr=%#x context=%d\n", vaddr, context_id);
+ DPRINTF(TLBVerbose, "Translating vaddr=%#x context=%d\n", vaddr, contextId);
// Translation enabled
- TlbEntry *te = lookup(vaddr, context_id);
+ TlbEntry *te = lookup(vaddr, contextId);
if (te == NULL) {
if (req->isPrefetch()){
//if the request is a prefetch don't attempt to fill the TLB
@@ -529,8 +526,8 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
// start translation table walk, pass variables rather than
// re-retreaving in table walker for speed
DPRINTF(TLB, "TLB Miss: Starting hardware table walker for %#x(%d)\n",
- vaddr, context_id);
- fault = tableWalker->walk(req, tc, context_id, mode, translation,
+ vaddr, contextId);
+ fault = tableWalker->walk(req, tc, contextId, mode, translation,
timing);
if (timing) {
delay = true;
@@ -540,7 +537,7 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
if (fault)
return fault;
- te = lookup(vaddr, context_id);
+ te = lookup(vaddr, contextId);
if (!te)
printTlb();
assert(te);
@@ -561,7 +558,7 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
setAttr(te->attributes);
if (te->nonCacheable)
req->setFlags(Request::UNCACHEABLE);
- uint32_t dacr = tc->readMiscReg(MISCREG_DACR);
+
switch ( (dacr >> (te->domain * 2)) & 0x3) {
case 0:
domainFaults++;
diff --git a/src/arch/arm/tlb.hh b/src/arch/arm/tlb.hh
index a6803c415..0b8bc1046 100644
--- a/src/arch/arm/tlb.hh
+++ b/src/arch/arm/tlb.hh
@@ -208,6 +208,32 @@ class TLB : public BaseTLB
void unserialize(Checkpoint *cp, const std::string &section);
void regStats();
+
+ // Caching misc register values here.
+ // Writing to misc registers needs to invalidate them.
+ // translateFunctional/translateSe/translateFs checks if they are
+ // invalid and call updateMiscReg if necessary.
+protected:
+ SCTLR sctlr;
+ bool isPriv;
+ uint32_t contextId;
+ PRRR prrr;
+ NMRR nmrr;
+ uint32_t dacr;
+ bool miscRegValid;
+ void updateMiscReg(ThreadContext *tc)
+ {
+ sctlr = tc->readMiscReg(MISCREG_SCTLR);
+ CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
+ isPriv = cpsr.mode != MODE_USER;
+ contextId = tc->readMiscReg(MISCREG_CONTEXTIDR);
+ prrr = tc->readMiscReg(MISCREG_PRRR);
+ nmrr = tc->readMiscReg(MISCREG_NMRR);
+ dacr = tc->readMiscReg(MISCREG_DACR);
+ miscRegValid = true;
+ }
+public:
+ inline void invalidateMiscReg() { miscRegValid = false; }
};
/* namespace ArmISA */ }
diff --git a/src/arch/arm/utility.cc b/src/arch/arm/utility.cc
index c42a8dddd..9293a4cfe 100644
--- a/src/arch/arm/utility.cc
+++ b/src/arch/arm/utility.cc
@@ -48,6 +48,8 @@
#include "mem/vport.hh"
#endif
+#include "arch/arm/tlb.hh"
+
namespace ArmISA {
void
@@ -148,7 +150,11 @@ copyRegs(ThreadContext *src, ThreadContext *dest)
// e.g. updateRegMap(val)
dest->setMiscReg(MISCREG_CPSR, src->readMiscRegNoEffect(MISCREG_CPSR));
- // Lastly copy PC/NPC
+ // Copy over the PC State
dest->pcState(src->pcState());
+
+ // Invalidate the tlb misc register cache
+ dest->getITBPtr()->invalidateMiscReg();
+ dest->getDTBPtr()->invalidateMiscReg();
}
}