X86: Fix the timing mode of the page table walker.
authorGabe Black <gblack@eecs.umich.edu>
Wed, 25 Feb 2009 18:16:34 +0000 (10:16 -0800)
committerGabe Black <gblack@eecs.umich.edu>
Wed, 25 Feb 2009 18:16:34 +0000 (10:16 -0800)
src/arch/x86/pagetable_walker.cc
src/arch/x86/pagetable_walker.hh

index fe3a4c3bbf903e2920474fa382626ca27dc6955d..87f00dcbea18f44daa1e02579818fa6b70ecef83 100644 (file)
@@ -85,7 +85,7 @@ BitUnion64(PageTableEntry)
 EndBitUnion(PageTableEntry)
 
 Fault
-Walker::doNext(PacketPtr &read, PacketPtr &write)
+Walker::doNext(PacketPtr &write)
 {
     assert(state != Ready && state != Waiting);
     write = NULL;
@@ -312,7 +312,6 @@ Walker::start(ThreadContext * _tc, BaseTLB::Translation *_translation,
         RequestPtr _req, bool _write, bool _execute)
 {
     assert(state == Ready);
-    assert(!tc);
     tc = _tc;
     req = _req;
     Addr vaddr = req->getVaddr();
@@ -366,21 +365,22 @@ Walker::start(ThreadContext * _tc, BaseTLB::Translation *_translation,
     read->allocate();
     Enums::MemoryMode memMode = sys->getMemoryMode();
     if (memMode == Enums::timing) {
+        nextState = state;
+        state = Waiting;
         timingFault = NoFault;
-        port.sendTiming(read);
+        sendPackets();
     } else if (memMode == Enums::atomic) {
         Fault fault;
         do {
             port.sendAtomic(read);
             PacketPtr write = NULL;
-            fault = doNext(read, write);
+            fault = doNext(write);
             assert(fault == NoFault || read == NULL);
             state = nextState;
             nextState = Ready;
             if (write)
                 port.sendAtomic(write);
         } while(read);
-        tc = NULL;
         state = Ready;
         nextState = Waiting;
         return fault;
@@ -399,18 +399,18 @@ Walker::WalkerPort::recvTiming(PacketPtr pkt)
 bool
 Walker::recvTiming(PacketPtr pkt)
 {
-    inflight--;
     if (pkt->isResponse() && !pkt->wasNacked()) {
+        assert(inflight);
+        assert(state == Waiting);
+        assert(!read);
+        inflight--;
         if (pkt->isRead()) {
-            assert(inflight);
-            assert(state == Waiting);
-            assert(!read);
             state = nextState;
             nextState = Ready;
             PacketPtr write = NULL;
-            timingFault = doNext(pkt, write);
-            state = Waiting;
             read = pkt;
+            timingFault = doNext(write);
+            state = Waiting;
             assert(timingFault == NoFault || read == NULL);
             if (write) {
                 writes.push_back(write);
@@ -420,7 +420,6 @@ Walker::recvTiming(PacketPtr pkt)
             sendPackets();
         }
         if (inflight == 0 && read == NULL && writes.size() == 0) {
-            tc = NULL;
             state = Ready;
             nextState = Waiting;
             if (timingFault == NoFault) {
@@ -445,6 +444,7 @@ Walker::recvTiming(PacketPtr pkt)
     } else if (pkt->wasNacked()) {
         pkt->reinitNacked();
         if (!port.sendTiming(pkt)) {
+            inflight--;
             retrying = true;
             if (pkt->isWrite()) {
                 writes.push_back(pkt);
@@ -452,8 +452,6 @@ Walker::recvTiming(PacketPtr pkt)
                 assert(!read);
                 read = pkt;
             }
-        } else {
-            inflight++;
         }
     }
     return true;
@@ -507,27 +505,26 @@ Walker::sendPackets()
 
     //Reads always have priority
     if (read) {
-        if (!port.sendTiming(read)) {
+        PacketPtr pkt = read;
+        read = NULL;
+        inflight++;
+        if (!port.sendTiming(pkt)) {
             retrying = true;
+            read = pkt;
+            inflight--;
             return;
-        } else {
-            inflight++;
-            delete read->req;
-            delete read;
-            read = NULL;
         }
     }
     //Send off as many of the writes as we can.
     while (writes.size()) {
         PacketPtr write = writes.back();
+        writes.pop_back();
+        inflight++;
         if (!port.sendTiming(write)) {
             retrying = true;
+            writes.push_back(write);
+            inflight--;
             return;
-        } else {
-            inflight++;
-            delete write->req;
-            delete write;
-            writes.pop_back();
         }
     }
 }
index 992711acdd0fdc87b5223fd1064a44b6fc560579..f73774a45e52c042c6813635b913df856a14e4fa 100644 (file)
@@ -85,15 +85,15 @@ namespace X86ISA
             PSEPD, PD, PTE
         };
 
-        // Act on the current state and determine what to do next. read
-        // should be the packet that just came back from a read and write
+        // Act on the current state and determine what to do next. The global
+        // read should be the packet that just came back from a read and write
         // should be NULL. When the function returns, read is either NULL
         // if the machine is finished, or points to a packet to initiate
         // the next read. If any write is required to update an "accessed"
         // bit, write will point to a packet to do the write. Otherwise it
         // will be NULL. The return value is whatever fault was incurred
         // during this stage of the lookup.
-        Fault doNext(PacketPtr &read, PacketPtr &write);
+        Fault doNext(PacketPtr &write);
 
         // Kick off the state machine.
         Fault start(ThreadContext * _tc, BaseTLB::Translation *translation,