arm: Fix TLB ignoring faults when table walking
authorAndrew Bardsley <Andrew.Bardsley@arm.com>
Tue, 2 Dec 2014 11:08:11 +0000 (06:08 -0500)
committerAndrew Bardsley <Andrew.Bardsley@arm.com>
Tue, 2 Dec 2014 11:08:11 +0000 (06:08 -0500)
This patch fixes a case where the Minor CPU can deadlock due to the lack
of a response to TLB request because of a bug in fault handling in the ARM
table walker.

TableWalker::processWalkWrapper is the scheduler-called wrapper which
handles deferred walks which calls to TableWalker::wait cannot immediately
process.  The handling of faults generated by processWalk{AArch64,LPAE,}
calls in those two functions is is different.  processWalkWrapper ignores
fault returns from processWalk... which can lead to ::finish not being
called on a translation.

This fix provides fault handling in processWalkWrapper similar to that
found in the leaf functions which BaseTLB::Translation::finish.

src/arch/arm/table_walker.cc

index 30fdf98117f694bb6edb0eb11bc7d8fa16be89da..6a0f0144a2a6bf783ea8a58602afb0ad9024d623 100644 (file)
@@ -344,12 +344,22 @@ TableWalker::processWalkWrapper()
         // We've got a valid request, lets process it
         pending = true;
         pendingQueue.pop_front();
+        // Keep currState in case one of the processWalk... calls NULLs it
+        WalkerState *curr_state_copy = currState;
+        Fault f;
         if (currState->aarch64)
-            processWalkAArch64();
+            f = processWalkAArch64();
         else if ((_haveLPAE && currState->ttbcr.eae) || currState->isHyp || isStage2)
-            processWalkLPAE();
+            f = processWalkLPAE();
         else
-            processWalk();
+            f = processWalk();
+
+        if (f != NoFault) {
+            curr_state_copy->transState->finish(f, curr_state_copy->req,
+                    curr_state_copy->tc, curr_state_copy->mode);
+
+            delete curr_state_copy;
+        }
         return;
     }