summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2009-02-25 10:16:34 -0800
committerGabe Black <gblack@eecs.umich.edu>2009-02-25 10:16:34 -0800
commit7462cb0842b9963d137cb578be6a0f7c619712d1 (patch)
tree204d6dc686c7f04dfc9c15f2d50ed0e954fc8688
parentf02df8cb7400d59c338abf44d2f7adfc9a665fa0 (diff)
downloadgem5-7462cb0842b9963d137cb578be6a0f7c619712d1.tar.xz
X86: Fix the timing mode of the page table walker.
-rw-r--r--src/arch/x86/pagetable_walker.cc47
-rw-r--r--src/arch/x86/pagetable_walker.hh6
2 files changed, 25 insertions, 28 deletions
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,