diff -r a11f79b70e42 -r 29f058c6b703 src/arch/arm/table_walker.cc --- a/src/arch/arm/table_walker.cc Wed Feb 26 10:53:31 2014 +0000 +++ b/src/arch/arm/table_walker.cc Wed Feb 26 10:54:16 2014 +0000 @@ -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()) {