ARM: Cache the misc regs at the TLB to limit readMiscReg() calls.
This commit is contained in:
parent
4c2e5c282b
commit
13931b9b82
|
@ -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);
|
||||
|
|
|
@ -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 §ion)
|
|||
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++;
|
||||
|
|
|
@ -208,6 +208,32 @@ class TLB : public BaseTLB
|
|||
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
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 */ }
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue