diff options
author | Andrew Bardsley <Andrew.Bardsley@arm.com> | 2014-12-02 06:08:11 -0500 |
---|---|---|
committer | Andrew Bardsley <Andrew.Bardsley@arm.com> | 2014-12-02 06:08:11 -0500 |
commit | 3cd0b1f6a6873ef06351dd49f3c7697175303371 (patch) | |
tree | fa84721b7b1c715fb078e3ad99e3f1ca1c73a912 /src/arch | |
parent | e5e5b80690f736c65c9b51ef96660637210f3938 (diff) | |
download | gem5-3cd0b1f6a6873ef06351dd49f3c7697175303371.tar.xz |
arm: Fix TLB ignoring faults when table walking
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.
Diffstat (limited to 'src/arch')
-rw-r--r-- | src/arch/arm/table_walker.cc | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc index 30fdf9811..6a0f0144a 100644 --- a/src/arch/arm/table_walker.cc +++ b/src/arch/arm/table_walker.cc @@ -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; } |