From 7462cb0842b9963d137cb578be6a0f7c619712d1 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:16:34 -0800 Subject: X86: Fix the timing mode of the page table walker. --- src/arch/x86/pagetable_walker.cc | 47 +++++++++++++++++++--------------------- src/arch/x86/pagetable_walker.hh | 6 ++--- 2 files changed, 25 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/arch/x86/pagetable_walker.cc b/src/arch/x86/pagetable_walker.cc index fe3a4c3bb..87f00dcbe 100644 --- a/src/arch/x86/pagetable_walker.cc +++ b/src/arch/x86/pagetable_walker.cc @@ -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(); } } } diff --git a/src/arch/x86/pagetable_walker.hh b/src/arch/x86/pagetable_walker.hh index 992711acd..f73774a45 100644 --- a/src/arch/x86/pagetable_walker.hh +++ b/src/arch/x86/pagetable_walker.hh @@ -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, -- cgit v1.2.3