x86: Squash outstanding walks when instructions are squashed.
authorGedare Bloom <gedare@rtems.org>
Tue, 21 May 2013 16:40:11 +0000 (11:40 -0500)
committerGedare Bloom <gedare@rtems.org>
Tue, 21 May 2013 16:40:11 +0000 (11:40 -0500)
This is the x86 version of the ARM changeset baa17ba80e06. In case an
instruction has been squashed by the o3 cpu, this patch allows page
table walker to avoid carrying out a pending translation that the
instruction requested for.

src/arch/x86/X86TLB.py
src/arch/x86/pagetable_walker.cc
src/arch/x86/pagetable_walker.hh

index a08dbb138be4ee32fbba42e1efec6e68a9211419..b652118cedb1509c5abb18ee5f77cb3b83f9fcaf 100644 (file)
@@ -47,6 +47,8 @@ class X86PagetableWalker(MemObject):
     cxx_header = 'arch/x86/pagetable_walker.hh'
     port = MasterPort("Port for the hardware table walker")
     system = Param.System(Parent.any, "system object")
+    num_squash_per_cycle = Param.Unsigned(4,
+            "Number of outstanding walks that can be squashed per cycle")
 
 class X86TLB(BaseTLB):
     type = 'X86TLB'
index 853e062e775c8e574869628da8fff6d8b45c2c12..45f902999a2faa0d39b58b018ef75e09a2a310e8 100644 (file)
@@ -139,11 +139,8 @@ Walker::recvTimingResp(PacketPtr pkt)
         delete senderWalk;
         // Since we block requests when another is outstanding, we
         // need to check if there is a waiting request to be serviced
-        if (currStates.size()) {
-            WalkerState * newState = currStates.front();
-            if (!newState->wasStarted())
-                newState->startWalk();
-        }
+        if (currStates.size())
+            startWalkWrapper();
     }
     return true;
 }
@@ -192,6 +189,36 @@ Walker::WalkerState::initState(ThreadContext * _tc,
     timing = _isTiming;
 }
 
+void
+Walker::startWalkWrapper()
+{
+    unsigned num_squashed = 0;
+    WalkerState *currState = currStates.front();
+    while ((num_squashed < numSquashable) && currState &&
+        currState->translation->squashed()) {
+        currStates.pop_front();
+        num_squashed++;
+
+        DPRINTF(PageTableWalker, "Squashing table walk for address %#x\n",
+            currState->req->getVaddr());
+
+        // finish the translation which will delete the translation object
+        currState->translation->finish(new UnimpFault("Squashed Inst"),
+                currState->req, currState->tc, currState->mode);
+
+        // delete the current request
+        delete currState;
+
+        // check the next translation request, if it exists
+        if (currStates.size())
+            currState = currStates.front();
+        else
+            currState = NULL;
+    }
+    if (currState && !currState->wasStarted())
+        currState->startWalk();
+}
+
 Fault
 Walker::WalkerState::startWalk()
 {
index c2781ca1b8ff851e73954e68ed27d85d57a35bb7..c6766689b6a750de0620691c0f7830d0885825c6 100644 (file)
@@ -87,6 +87,7 @@ namespace X86ISA
         // State to track each walk of the page table
         class WalkerState
         {
+          friend class Walker;
           private:
             enum State {
                 Ready,
@@ -176,6 +177,12 @@ namespace X86ISA
         System * sys;
         MasterID masterId;
 
+        // The number of outstanding walks that can be squashed per cycle.
+        unsigned numSquashable;
+
+        // Wrapper for checking for squashes before starting a translation.
+        void startWalkWrapper();
+
         // Functions for dealing with packets.
         bool recvTimingResp(PacketPtr pkt);
         void recvRetry();
@@ -199,7 +206,8 @@ namespace X86ISA
         Walker(const Params *params) :
             MemObject(params), port(name() + ".port", this),
             funcState(this, NULL, NULL, true), tlb(NULL), sys(params->system),
-            masterId(sys->getMasterId(name()))
+            masterId(sys->getMasterId(name())),
+            numSquashable(params->num_squash_per_cycle)
         {
         }
     };