changeset 508aebb47ca6 in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=508aebb47ca6
description:
arm: fix a page table walker issue where a page could be translated
multiple times
If multiple memory operations to the same page are miss the TLB they are
all inserted into the page table queue and before this change could
result
in multiple uncessesary walks as well as duplicate enteries being
inserted
into the TLB.
diffstat:
src/arch/arm/table_walker.cc | 31 +++++++++++++++++++++++--------
src/arch/arm/tlb.cc | 2 +-
src/arch/arm/tlb.hh | 16 ++++++++--------
3 files changed, 32 insertions(+), 17 deletions(-)
diffs (107 lines):
diff -r 5de6389b72f7 -r 508aebb47ca6 src/arch/arm/table_walker.cc
--- a/src/arch/arm/table_walker.cc Fri Feb 15 17:40:10 2013 -0500
+++ b/src/arch/arm/table_walker.cc Fri Feb 15 17:40:10 2013 -0500
@@ -186,8 +186,15 @@
assert(pendingQueue.size());
currState = pendingQueue.front();
+ // Check if a previous walk filled this request already
+ TlbEntry* te = tlb->lookup(currState->vaddr, currState->contextId, true);
- if (!currState->transState->squashed()) {
+ // 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 @@
// 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 -r 5de6389b72f7 -r 508aebb47ca6 src/arch/arm/tlb.cc
--- a/src/arch/arm/tlb.cc Fri Feb 15 17:40:10 2013 -0500
+++ b/src/arch/arm/tlb.cc Fri Feb 15 17:40:10 2013 -0500
@@ -107,7 +107,7 @@
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 -r 5de6389b72f7 -r 508aebb47ca6 src/arch/arm/tlb.hh
--- a/src/arch/arm/tlb.hh Fri Feb 15 17:40:10 2013 -0500
+++ b/src/arch/arm/tlb.hh Fri Feb 15 17:40:10 2013 -0500
@@ -91,14 +91,6 @@
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 @@
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; }
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev