diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/arch/arm/isa.cc | 20 | ||||
-rw-r--r-- | src/arch/arm/tlb.cc | 41 | ||||
-rw-r--r-- | src/arch/arm/tlb.hh | 26 | ||||
-rw-r--r-- | src/arch/arm/utility.cc | 8 |
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 §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++; 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 §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 */ } 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(); } } |