changeset b58c5c5854de in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=b58c5c5854de
description:
        arm: Handle functional TLB walks properly

        The table walker code currently accounts for two types of walks,
        Atomic and Timing, and treats them differently. Atomic walks keep a
        single instance of WalkerState around for all walks to use in
        currState. Timing mode keeps a queue of in-flight WalkerStates and
        maintains currState as NULL between walks.

        If a functional walk is done during Timing mode, it is treated as an
        atomic walk and either creates a persistent WalkerState if in between
        Timing walks, or stomps an existing currState for an in-progress
        Timing walk.

        This patch distinguishes functional walks as being able to exist at
        any time and sets up a temporary WalkerState for its exclusive use and
        then cleans up when finished, leaving any in progress Atomic or Timing
        walks undisturbed.

diffstat:

 src/arch/arm/table_walker.cc |  26 ++++++++++++++++++++++----
 1 files changed, 22 insertions(+), 4 deletions(-)

diffs (54 lines):

diff -r 83bb6e381cbf -r b58c5c5854de src/arch/arm/table_walker.cc
--- a/src/arch/arm/table_walker.cc      Fri Mar 07 15:56:23 2014 -0500
+++ b/src/arch/arm/table_walker.cc      Fri Mar 07 15:56:23 2014 -0500
@@ -160,8 +160,9 @@
                   bool secure, TLB::ArmTranslationType tranType)
 {
     assert(!(_functional && _timing));
+    WalkerState *savedCurrState = NULL;
 
-    if (!currState) {
+    if (!currState && !_functional) {
         // For atomic mode, a new WalkerState instance should be only created
         // once per TLB. For timing mode, a new instance is generated for every
         // TLB miss.
@@ -169,6 +170,14 @@
 
         currState = new WalkerState();
         currState->tableWalker = this;
+    } else if (_functional) {
+        // If we are mixing functional mode with timing (or even
+        // atomic), we need to to be careful and clean up after
+        // ourselves to not risk getting into an inconsistent state.
+        DPRINTF(TLBVerbose, "creating functional instance of WalkerState\n");
+        savedCurrState = currState;
+        currState = new WalkerState();
+        currState->tableWalker = this;
     } else if (_timing) {
         // This is a translation that was completed and then faulted again
         // because some underlying parameters that affect the translation
@@ -264,12 +273,21 @@
     }
 
     if (!currState->timing) {
+        Fault fault = NoFault;
         if (currState->aarch64)
-            return processWalkAArch64();
+            fault = processWalkAArch64();
         else if (long_desc_format)
-            return processWalkLPAE();
+            fault = processWalkLPAE();
         else
-            return processWalk();
+            fault = processWalk();
+
+        // If this was a functional non-timing access restore state to
+        // how we found it.
+        if (currState->functional) {
+            delete currState;
+            currState = savedCurrState;
+        }
+        return fault;
     }
 
     if (pending || pendingQueue.size()) {
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to