summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/arm/table_walker.cc33
-rw-r--r--src/arch/arm/tlb.cc2
-rw-r--r--src/arch/arm/tlb.hh16
3 files changed, 33 insertions, 18 deletions
diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc
index 44f12833b..9755299ff 100644
--- a/src/arch/arm/table_walker.cc
+++ b/src/arch/arm/table_walker.cc
@@ -186,8 +186,15 @@ TableWalker::processWalkWrapper()
assert(pendingQueue.size());
currState = pendingQueue.front();
-
- if (!currState->transState->squashed()) {
+ // Check if a previous walk filled this request already
+ TlbEntry* te = tlb->lookup(currState->vaddr, currState->contextId, true);
+
+ // Check if we still need to have a walk for this request. If the requesting
+ // instruction has been squashed, or a previous walk has filled the TLB with
+ // a match, we just want to get rid of the walk. The latter could happen
+ // when there are multiple outstanding misses to a single page and a
+ // previous request has been successfully translated.
+ if (!currState->transState->squashed() && !te) {
// We've got a valid request, lets process it
pending = true;
pendingQueue.pop_front();
@@ -200,26 +207,34 @@ TableWalker::processWalkWrapper()
// squashed we shouldn't bother.
unsigned num_squashed = 0;
ThreadContext *tc = currState->tc;
- assert(currState->transState->squashed());
while ((num_squashed < numSquashable) && currState &&
- currState->transState->squashed()) {
+ (currState->transState->squashed() || te)) {
pendingQueue.pop_front();
num_squashed++;
DPRINTF(TLB, "Squashing table walk for address %#x\n", currState->vaddr);
- // finish the translation which will delete the translation object
- currState->transState->finish(new UnimpFault("Squashed Inst"),
- currState->req, currState->tc, currState->mode);
+ if (currState->transState->squashed()) {
+ // finish the translation which will delete the translation object
+ currState->transState->finish(new UnimpFault("Squashed Inst"),
+ currState->req, currState->tc, currState->mode);
+ } else {
+ // translate the request now that we know it will work
+ currState->fault = tlb->translateTiming(currState->req, currState->tc,
+ currState->transState, currState->mode);
+ }
// delete the current request
delete currState;
// peak at the next one
- if (pendingQueue.size())
+ if (pendingQueue.size()) {
currState = pendingQueue.front();
- else
+ te = tlb->lookup(currState->vaddr, currState->contextId, true);
+ } else {
+ // Terminate the loop, nothing more to do
currState = NULL;
+ }
}
// if we've still got pending translations schedule more work
diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc
index 170d819d8..6b864b980 100644
--- a/src/arch/arm/tlb.cc
+++ b/src/arch/arm/tlb.cc
@@ -107,7 +107,7 @@ TLB::lookup(Addr va, uint8_t cid, bool functional)
if (table[x].match(va, cid)) {
// We only move the hit entry ahead when the position is higher than rangeMRU
- if (x > rangeMRU) {
+ if (x > rangeMRU && !functional) {
TlbEntry tmp_entry = table[x];
for(int i = x; i > 0; i--)
table[i] = table[i-1];
diff --git a/src/arch/arm/tlb.hh b/src/arch/arm/tlb.hh
index f5c7320ed..c1eba1ba7 100644
--- a/src/arch/arm/tlb.hh
+++ b/src/arch/arm/tlb.hh
@@ -91,14 +91,6 @@ class TLB : public BaseTLB
TableWalker *tableWalker;
- /** Lookup an entry in the TLB
- * @param vpn virtual address
- * @param asn context id/address space id to use
- * @param functional if the lookup should modify state
- * @return pointer to TLB entrry if it exists
- */
- TlbEntry *lookup(Addr vpn, uint8_t asn, bool functional = false);
-
// Access Stats
mutable Stats::Scalar instHits;
mutable Stats::Scalar instMisses;
@@ -132,6 +124,14 @@ class TLB : public BaseTLB
typedef ArmTLBParams Params;
TLB(const Params *p);
+ /** Lookup an entry in the TLB
+ * @param vpn virtual address
+ * @param asn context id/address space id to use
+ * @param functional if the lookup should modify state
+ * @return pointer to TLB entrry if it exists
+ */
+ TlbEntry *lookup(Addr vpn, uint8_t asn, bool functional = false);
+
virtual ~TLB();
int getsize() const { return size; }