ARM: Cache the misc regs at the TLB to limit readMiscReg() calls.

This commit is contained in:
Ali Saidi 2010-11-15 14:04:03 -06:00
parent 4c2e5c282b
commit 13931b9b82
4 changed files with 72 additions and 23 deletions

View file

@ -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);

View file

@ -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++;

View file

@ -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 */ }

View file

@ -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();
}
}