ARM: Cache the misc regs at the TLB to limit readMiscReg() calls.
authorAli Saidi <Ali.Saidi@ARM.com>
Mon, 15 Nov 2010 20:04:03 +0000 (14:04 -0600)
committerAli Saidi <Ali.Saidi@ARM.com>
Mon, 15 Nov 2010 20:04:03 +0000 (14:04 -0600)
src/arch/arm/isa.cc
src/arch/arm/tlb.cc
src/arch/arm/tlb.hh
src/arch/arm/utility.cc

index 20cddcff16c5b808a20bfd3fdab466fc51e92e57..67062be41815a3d7019a54bbeb6f7f6d1d8d1451 100644 (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);
index 53509372adfbc89e4a6e254096faf011c8381f25..6d6da15c805ca85040fad98b7d1c51efb35612f3 100644 (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++;
index a6803c415974b0fe432ae11fc1260c9aa6522e91..0b8bc1046ea9d2d565587a2c02d53c725f52906e 100644 (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 */ }
index c42a8dddd9498d152c47cb5ace4178113aa70f96..9293a4cfee2408bfeb5b117088e56d2a1da0b9bb 100644 (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();
 }
 }