X86: Make the X86 TLB take advantage of delayed translations, and get rid of the fake TLB miss faults.

This commit is contained in:
Gabe Black 2009-02-25 10:16:21 -08:00
parent 6ed47e9464
commit 40fdba2454
6 changed files with 187 additions and 192 deletions

View file

@ -163,56 +163,6 @@ namespace X86ISA
} }
} }
void FakeITLBFault::invoke(ThreadContext * tc)
{
// Start the page table walker.
tc->getITBPtr()->walk(tc, vaddr, write, execute);
}
void FakeDTLBFault::invoke(ThreadContext * tc)
{
// Start the page table walker.
tc->getDTBPtr()->walk(tc, vaddr, write, execute);
}
#else // !FULL_SYSTEM
void FakeITLBFault::invoke(ThreadContext * tc)
{
DPRINTF(TLB, "Invoking an ITLB fault for address %#x at pc %#x.\n",
vaddr, tc->readPC());
Process *p = tc->getProcessPtr();
TlbEntry entry;
bool success = p->pTable->lookup(vaddr, entry);
if(!success) {
panic("Tried to execute unmapped address %#x.\n", vaddr);
} else {
Addr alignedVaddr = p->pTable->pageAlign(vaddr);
DPRINTF(TLB, "Mapping %#x to %#x\n", alignedVaddr,
entry.pageStart());
tc->getITBPtr()->insert(alignedVaddr, entry);
}
}
void FakeDTLBFault::invoke(ThreadContext * tc)
{
DPRINTF(TLB, "Invoking an DTLB fault for address %#x at pc %#x.\n",
vaddr, tc->readPC());
Process *p = tc->getProcessPtr();
TlbEntry entry;
bool success = p->pTable->lookup(vaddr, entry);
if(!success) {
p->checkAndAllocNextPage(vaddr);
success = p->pTable->lookup(vaddr, entry);
}
if(!success) {
panic("Tried to access unmapped address %#x.\n", vaddr);
} else {
Addr alignedVaddr = p->pTable->pageAlign(vaddr);
DPRINTF(TLB, "Mapping %#x to %#x\n", alignedVaddr,
entry.pageStart());
tc->getDTBPtr()->insert(alignedVaddr, entry);
}
}
#endif #endif
} // namespace X86ISA } // namespace X86ISA

View file

@ -422,38 +422,6 @@ namespace X86ISA
return true; return true;
} }
}; };
// These faults aren't part of the ISA definition. They trigger filling
// the tlb on a miss and are to take the place of a hardware table walker.
class FakeITLBFault : public X86Fault
{
protected:
Addr vaddr;
bool write;
bool execute;
public:
FakeITLBFault(Addr _vaddr, bool _write, bool _execute) :
X86Fault("fake instruction tlb fault", "itlb", 0),
vaddr(_vaddr), write(_write), execute(_execute)
{}
void invoke(ThreadContext * tc);
};
class FakeDTLBFault : public X86Fault
{
protected:
Addr vaddr;
bool write;
bool execute;
public:
FakeDTLBFault(Addr _vaddr, bool _write, bool _execute) :
X86Fault("fake data tlb fault", "dtlb", 0),
vaddr(_vaddr), write(_write), execute(_execute)
{}
void invoke(ThreadContext * tc);
};
}; };
#endif // __ARCH_X86_FAULTS_HH__ #endif // __ARCH_X86_FAULTS_HH__

View file

@ -84,7 +84,7 @@ BitUnion64(PageTableEntry)
Bitfield<0> p; Bitfield<0> p;
EndBitUnion(PageTableEntry) EndBitUnion(PageTableEntry)
void Fault
Walker::doNext(PacketPtr &read, PacketPtr &write) Walker::doNext(PacketPtr &read, PacketPtr &write)
{ {
assert(state != Ready && state != Waiting); assert(state != Ready && state != Waiting);
@ -106,11 +106,11 @@ Walker::doNext(PacketPtr &read, PacketPtr &write)
pte.a = 1; pte.a = 1;
entry.writable = pte.w; entry.writable = pte.w;
entry.user = pte.u; entry.user = pte.u;
if (badNX) if (badNX || !pte.p) {
panic("NX violation!\n"); stop();
return pageFault(pte.p);
}
entry.noExec = pte.nx; entry.noExec = pte.nx;
if (!pte.p)
panic("Page at %#x not present!\n", entry.vaddr);
nextState = LongPDP; nextState = LongPDP;
break; break;
case LongPDP: case LongPDP:
@ -119,10 +119,10 @@ Walker::doNext(PacketPtr &read, PacketPtr &write)
pte.a = 1; pte.a = 1;
entry.writable = entry.writable && pte.w; entry.writable = entry.writable && pte.w;
entry.user = entry.user && pte.u; entry.user = entry.user && pte.u;
if (badNX) if (badNX || !pte.p) {
panic("NX violation!\n"); stop();
if (!pte.p) return pageFault(pte.p);
panic("Page at %#x not present!\n", entry.vaddr); }
nextState = LongPD; nextState = LongPD;
break; break;
case LongPD: case LongPD:
@ -130,10 +130,10 @@ Walker::doNext(PacketPtr &read, PacketPtr &write)
pte.a = 1; pte.a = 1;
entry.writable = entry.writable && pte.w; entry.writable = entry.writable && pte.w;
entry.user = entry.user && pte.u; entry.user = entry.user && pte.u;
if (badNX) if (badNX || !pte.p) {
panic("NX violation!\n"); stop();
if (!pte.p) return pageFault(pte.p);
panic("Page at %#x not present!\n", entry.vaddr); }
if (!pte.ps) { if (!pte.ps) {
// 4 KB page // 4 KB page
entry.size = 4 * (1 << 10); entry.size = 4 * (1 << 10);
@ -150,36 +150,32 @@ Walker::doNext(PacketPtr &read, PacketPtr &write)
entry.patBit = bits(pte, 12); entry.patBit = bits(pte, 12);
entry.vaddr = entry.vaddr & ~((2 * (1 << 20)) - 1); entry.vaddr = entry.vaddr & ~((2 * (1 << 20)) - 1);
tlb->insert(entry.vaddr, entry); tlb->insert(entry.vaddr, entry);
nextState = Ready; stop();
delete read->req; return NoFault;
delete read;
read = NULL;
return;
} }
case LongPTE: case LongPTE:
doWrite = !pte.a; doWrite = !pte.a;
pte.a = 1; pte.a = 1;
entry.writable = entry.writable && pte.w; entry.writable = entry.writable && pte.w;
entry.user = entry.user && pte.u; entry.user = entry.user && pte.u;
if (badNX) if (badNX || !pte.p) {
panic("NX violation!\n"); stop();
if (!pte.p) return pageFault(pte.p);
panic("Page at %#x not present!\n", entry.vaddr); }
entry.paddr = (uint64_t)pte & (mask(40) << 12); entry.paddr = (uint64_t)pte & (mask(40) << 12);
entry.uncacheable = uncacheable; entry.uncacheable = uncacheable;
entry.global = pte.g; entry.global = pte.g;
entry.patBit = bits(pte, 12); entry.patBit = bits(pte, 12);
entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1); entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1);
tlb->insert(entry.vaddr, entry); tlb->insert(entry.vaddr, entry);
nextState = Ready; stop();
delete read->req; return NoFault;
delete read;
read = NULL;
return;
case PAEPDP: case PAEPDP:
nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.pael2 * size; nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.pael2 * size;
if (!pte.p) if (!pte.p) {
panic("Page at %#x not present!\n", entry.vaddr); stop();
return pageFault(pte.p);
}
nextState = PAEPD; nextState = PAEPD;
break; break;
case PAEPD: case PAEPD:
@ -187,10 +183,10 @@ Walker::doNext(PacketPtr &read, PacketPtr &write)
pte.a = 1; pte.a = 1;
entry.writable = pte.w; entry.writable = pte.w;
entry.user = pte.u; entry.user = pte.u;
if (badNX) if (badNX || !pte.p) {
panic("NX violation!\n"); stop();
if (!pte.p) return pageFault(pte.p);
panic("Page at %#x not present!\n", entry.vaddr); }
if (!pte.ps) { if (!pte.ps) {
// 4 KB page // 4 KB page
entry.size = 4 * (1 << 10); entry.size = 4 * (1 << 10);
@ -206,39 +202,35 @@ Walker::doNext(PacketPtr &read, PacketPtr &write)
entry.patBit = bits(pte, 12); entry.patBit = bits(pte, 12);
entry.vaddr = entry.vaddr & ~((2 * (1 << 20)) - 1); entry.vaddr = entry.vaddr & ~((2 * (1 << 20)) - 1);
tlb->insert(entry.vaddr, entry); tlb->insert(entry.vaddr, entry);
nextState = Ready; stop();
delete read->req; return NoFault;
delete read;
read = NULL;
return;
} }
case PAEPTE: case PAEPTE:
doWrite = !pte.a; doWrite = !pte.a;
pte.a = 1; pte.a = 1;
entry.writable = entry.writable && pte.w; entry.writable = entry.writable && pte.w;
entry.user = entry.user && pte.u; entry.user = entry.user && pte.u;
if (badNX) if (badNX || !pte.p) {
panic("NX violation!\n"); stop();
if (!pte.p) return pageFault(pte.p);
panic("Page at %#x not present!\n", entry.vaddr); }
entry.paddr = (uint64_t)pte & (mask(40) << 12); entry.paddr = (uint64_t)pte & (mask(40) << 12);
entry.uncacheable = uncacheable; entry.uncacheable = uncacheable;
entry.global = pte.g; entry.global = pte.g;
entry.patBit = bits(pte, 7); entry.patBit = bits(pte, 7);
entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1); entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1);
tlb->insert(entry.vaddr, entry); tlb->insert(entry.vaddr, entry);
nextState = Ready; stop();
delete read->req; return NoFault;
delete read;
read = NULL;
return;
case PSEPD: case PSEPD:
doWrite = !pte.a; doWrite = !pte.a;
pte.a = 1; pte.a = 1;
entry.writable = pte.w; entry.writable = pte.w;
entry.user = pte.u; entry.user = pte.u;
if (!pte.p) if (!pte.p) {
panic("Page at %#x not present!\n", entry.vaddr); stop();
return pageFault(pte.p);
}
if (!pte.ps) { if (!pte.ps) {
// 4 KB page // 4 KB page
entry.size = 4 * (1 << 10); entry.size = 4 * (1 << 10);
@ -255,44 +247,40 @@ Walker::doNext(PacketPtr &read, PacketPtr &write)
entry.patBit = bits(pte, 12); entry.patBit = bits(pte, 12);
entry.vaddr = entry.vaddr & ~((4 * (1 << 20)) - 1); entry.vaddr = entry.vaddr & ~((4 * (1 << 20)) - 1);
tlb->insert(entry.vaddr, entry); tlb->insert(entry.vaddr, entry);
nextState = Ready; stop();
delete read->req; return NoFault;
delete read;
read = NULL;
return;
} }
case PD: case PD:
doWrite = !pte.a; doWrite = !pte.a;
pte.a = 1; pte.a = 1;
entry.writable = pte.w; entry.writable = pte.w;
entry.user = pte.u; entry.user = pte.u;
if (!pte.p) if (!pte.p) {
panic("Page at %#x not present!\n", entry.vaddr); stop();
return pageFault(pte.p);
}
// 4 KB page // 4 KB page
entry.size = 4 * (1 << 10); entry.size = 4 * (1 << 10);
nextRead = ((uint64_t)pte & (mask(20) << 12)) + vaddr.norml2 * size; nextRead = ((uint64_t)pte & (mask(20) << 12)) + vaddr.norml2 * size;
nextState = PTE; nextState = PTE;
break; break;
nextState = PTE;
break;
case PTE: case PTE:
doWrite = !pte.a; doWrite = !pte.a;
pte.a = 1; pte.a = 1;
entry.writable = pte.w; entry.writable = pte.w;
entry.user = pte.u; entry.user = pte.u;
if (!pte.p) if (!pte.p) {
panic("Page at %#x not present!\n", entry.vaddr); stop();
return pageFault(pte.p);
}
entry.paddr = (uint64_t)pte & (mask(20) << 12); entry.paddr = (uint64_t)pte & (mask(20) << 12);
entry.uncacheable = uncacheable; entry.uncacheable = uncacheable;
entry.global = pte.g; entry.global = pte.g;
entry.patBit = bits(pte, 7); entry.patBit = bits(pte, 7);
entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1); entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1);
tlb->insert(entry.vaddr, entry); tlb->insert(entry.vaddr, entry);
nextState = Ready; stop();
delete read->req; return NoFault;
delete read;
read = NULL;
return;
default: default:
panic("Unknown page table walker state %d!\n"); panic("Unknown page table walker state %d!\n");
} }
@ -316,16 +304,21 @@ Walker::doNext(PacketPtr &read, PacketPtr &write)
delete oldRead->req; delete oldRead->req;
delete oldRead; delete oldRead;
} }
return NoFault;
} }
void Fault
Walker::start(ThreadContext * _tc, Addr vaddr, bool _write, bool _execute) Walker::start(ThreadContext * _tc, BaseTLB::Translation *_translation,
RequestPtr _req, bool _write, bool _execute)
{ {
assert(state == Ready); assert(state == Ready);
assert(!tc); assert(!tc);
tc = _tc; tc = _tc;
req = _req;
Addr vaddr = req->getVaddr();
execute = _execute; execute = _execute;
write = _write; write = _write;
translation = _translation;
VAddr addr = vaddr; VAddr addr = vaddr;
@ -339,6 +332,7 @@ Walker::start(ThreadContext * _tc, Addr vaddr, bool _write, bool _execute)
// Do long mode. // Do long mode.
state = LongPML4; state = LongPML4;
top = (cr3.longPdtb << 12) + addr.longl4 * size; top = (cr3.longPdtb << 12) + addr.longl4 * size;
enableNX = efer.nxe;
} else { } else {
// We're in some flavor of legacy mode. // We're in some flavor of legacy mode.
CR4 cr4 = tc->readMiscRegNoEffect(MISCREG_CR4); CR4 cr4 = tc->readMiscRegNoEffect(MISCREG_CR4);
@ -346,6 +340,7 @@ Walker::start(ThreadContext * _tc, Addr vaddr, bool _write, bool _execute)
// Do legacy PAE. // Do legacy PAE.
state = PAEPDP; state = PAEPDP;
top = (cr3.paePdtb << 5) + addr.pael3 * size; top = (cr3.paePdtb << 5) + addr.pael3 * size;
enableNX = efer.nxe;
} else { } else {
size = 4; size = 4;
top = (cr3.pdtb << 12) + addr.norml2 * size; top = (cr3.pdtb << 12) + addr.norml2 * size;
@ -356,14 +351,13 @@ Walker::start(ThreadContext * _tc, Addr vaddr, bool _write, bool _execute)
// Do legacy non PSE. // Do legacy non PSE.
state = PD; state = PD;
} }
enableNX = false;
} }
} }
nextState = Ready; nextState = Ready;
entry.vaddr = vaddr; entry.vaddr = vaddr;
enableNX = efer.nxe;
Request::Flags flags = Request::PHYSICAL; Request::Flags flags = Request::PHYSICAL;
if (cr3.pcd) if (cr3.pcd)
flags.set(Request::UNCACHEABLE); flags.set(Request::UNCACHEABLE);
@ -372,13 +366,15 @@ Walker::start(ThreadContext * _tc, Addr vaddr, bool _write, bool _execute)
read->allocate(); read->allocate();
Enums::MemoryMode memMode = sys->getMemoryMode(); Enums::MemoryMode memMode = sys->getMemoryMode();
if (memMode == Enums::timing) { if (memMode == Enums::timing) {
tc->suspend(); timingFault = NoFault;
port.sendTiming(read); port.sendTiming(read);
} else if (memMode == Enums::atomic) { } else if (memMode == Enums::atomic) {
Fault fault;
do { do {
port.sendAtomic(read); port.sendAtomic(read);
PacketPtr write = NULL; PacketPtr write = NULL;
doNext(read, write); fault = doNext(read, write);
assert(fault == NoFault || read == NULL);
state = nextState; state = nextState;
nextState = Ready; nextState = Ready;
if (write) if (write)
@ -387,9 +383,11 @@ Walker::start(ThreadContext * _tc, Addr vaddr, bool _write, bool _execute)
tc = NULL; tc = NULL;
state = Ready; state = Ready;
nextState = Waiting; nextState = Waiting;
return fault;
} else { } else {
panic("Unrecognized memory system mode.\n"); panic("Unrecognized memory system mode.\n");
} }
return NoFault;
} }
bool bool
@ -410,9 +408,10 @@ Walker::recvTiming(PacketPtr pkt)
state = nextState; state = nextState;
nextState = Ready; nextState = Ready;
PacketPtr write = NULL; PacketPtr write = NULL;
doNext(pkt, write); timingFault = doNext(pkt, write);
state = Waiting; state = Waiting;
read = pkt; read = pkt;
assert(timingFault == NoFault || read == NULL);
if (write) { if (write) {
writes.push_back(write); writes.push_back(write);
} }
@ -421,10 +420,27 @@ Walker::recvTiming(PacketPtr pkt)
sendPackets(); sendPackets();
} }
if (inflight == 0 && read == NULL && writes.size() == 0) { if (inflight == 0 && read == NULL && writes.size() == 0) {
tc->activate(0);
tc = NULL; tc = NULL;
state = Ready; state = Ready;
nextState = Waiting; nextState = Waiting;
if (timingFault == NoFault) {
/*
* Finish the translation. Now that we now the right entry is
* in the TLB, this should work with no memory accesses.
* There could be new faults unrelated to the table walk like
* permissions violations, so we'll need the return value as
* well.
*/
bool delayedResponse;
Fault fault = tlb->translate(req, tc, NULL, write, execute,
delayedResponse, true);
assert(!delayedResponse);
// Let the CPU continue.
translation->finish(fault, req, tc, write);
} else {
// There was a fault during the walk. Let the CPU know.
translation->finish(timingFault, req, tc, write);
}
} }
} else if (pkt->wasNacked()) { } else if (pkt->wasNacked()) {
pkt->reinitNacked(); pkt->reinitNacked();
@ -525,6 +541,14 @@ Walker::getPort(const std::string &if_name, int idx)
panic("No page table walker port named %s!\n", if_name); panic("No page table walker port named %s!\n", if_name);
} }
Fault
Walker::pageFault(bool present)
{
HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
return new PageFault(entry.vaddr, present, write,
m5reg.cpl == 3, false, execute && enableNX);
}
} }
X86ISA::Walker * X86ISA::Walker *

View file

@ -91,11 +91,22 @@ namespace X86ISA
// if the machine is finished, or points to a packet to initiate // if the machine is finished, or points to a packet to initiate
// the next read. If any write is required to update an "accessed" // 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 // bit, write will point to a packet to do the write. Otherwise it
// will be NULL. // will be NULL. The return value is whatever fault was incurred
void doNext(PacketPtr &read, PacketPtr &write); // during this stage of the lookup.
Fault doNext(PacketPtr &read, PacketPtr &write);
// Kick off the state machine. // Kick off the state machine.
void start(ThreadContext * _tc, Addr vaddr, bool write, bool execute); Fault start(ThreadContext * _tc, BaseTLB::Translation *translation,
RequestPtr req, bool write, bool execute);
// Clean up after the state machine.
void
stop()
{
nextState = Ready;
delete read->req;
delete read;
read = NULL;
}
protected: protected:
@ -110,6 +121,11 @@ namespace X86ISA
bool retrying; bool retrying;
/*
* The fault, if any, that's waiting to be delivered in timing mode.
*/
Fault timingFault;
/* /*
* Functions for dealing with packets. * Functions for dealing with packets.
*/ */
@ -156,16 +172,18 @@ namespace X86ISA
// The TLB we're supposed to load. // The TLB we're supposed to load.
TLB * tlb; TLB * tlb;
System * sys; System * sys;
BaseTLB::Translation * translation;
/* /*
* State machine state. * State machine state.
*/ */
ThreadContext * tc; ThreadContext * tc;
RequestPtr req;
State state; State state;
State nextState; State nextState;
int size; int size;
bool enableNX; bool enableNX;
bool write, execute; bool write, execute, user;
TlbEntry entry; TlbEntry entry;
Fault pageFault(bool present); Fault pageFault(bool present);

View file

@ -72,6 +72,9 @@
#if FULL_SYSTEM #if FULL_SYSTEM
#include "arch/x86/pagetable_walker.hh" #include "arch/x86/pagetable_walker.hh"
#else
#include "mem/page_table.hh"
#include "sim/process.hh"
#endif #endif
namespace X86ISA { namespace X86ISA {
@ -90,7 +93,7 @@ TLB::TLB(const Params *p) : BaseTLB(p), configAddress(0), size(p->size)
#endif #endif
} }
void TlbEntry *
TLB::insert(Addr vpn, TlbEntry &entry) TLB::insert(Addr vpn, TlbEntry &entry)
{ {
//TODO Deal with conflicting entries //TODO Deal with conflicting entries
@ -106,6 +109,7 @@ TLB::insert(Addr vpn, TlbEntry &entry)
*newEntry = entry; *newEntry = entry;
newEntry->vaddr = vpn; newEntry->vaddr = vpn;
entryList.push_front(newEntry); entryList.push_front(newEntry);
return newEntry;
} }
TLB::EntryList::iterator TLB::EntryList::iterator
@ -138,14 +142,6 @@ TLB::lookup(Addr va, bool update_lru)
return *entry; return *entry;
} }
#if FULL_SYSTEM
void
TLB::walk(ThreadContext * _tc, Addr vaddr, bool write, bool execute)
{
walker->start(_tc, vaddr, write, execute);
}
#endif
void void
TLB::invalidateAll() TLB::invalidateAll()
{ {
@ -188,11 +184,12 @@ TLB::demapPage(Addr va, uint64_t asn)
} }
} }
template<class TlbFault>
Fault Fault
TLB::translateAtomic(RequestPtr req, ThreadContext *tc, TLB::translate(RequestPtr req, ThreadContext *tc,
bool write, bool execute) Translation *translation, bool write, bool execute,
bool &delayedResponse, bool timing)
{ {
delayedResponse = false;
Addr vaddr = req->getVaddr(); Addr vaddr = req->getVaddr();
DPRINTF(TLB, "Translating vaddr %#x.\n", vaddr); DPRINTF(TLB, "Translating vaddr %#x.\n", vaddr);
uint32_t flags = req->getFlags(); uint32_t flags = req->getFlags();
@ -617,14 +614,45 @@ TLB::translateAtomic(RequestPtr req, ThreadContext *tc,
// The vaddr already has the segment base applied. // The vaddr already has the segment base applied.
TlbEntry *entry = lookup(vaddr); TlbEntry *entry = lookup(vaddr);
if (!entry) { if (!entry) {
return new TlbFault(vaddr, write, execute); #if FULL_SYSTEM
Fault fault = walker->start(tc, translation, req,
write, execute);
if (timing || fault != NoFault) {
// This gets ignored in atomic mode.
delayedResponse = true;
return fault;
}
entry = lookup(vaddr);
assert(entry);
#else
DPRINTF(TLB, "Handling a TLB miss for "
"address %#x at pc %#x.\n",
vaddr, tc->readPC());
Process *p = tc->getProcessPtr();
TlbEntry newEntry;
bool success = p->pTable->lookup(vaddr, newEntry);
if(!success && !execute) {
p->checkAndAllocNextPage(vaddr);
success = p->pTable->lookup(vaddr, newEntry);
}
if(!success) {
panic("Tried to execute unmapped address %#x.\n", vaddr);
} else { } else {
Addr alignedVaddr = p->pTable->pageAlign(vaddr);
DPRINTF(TLB, "Mapping %#x to %#x\n", alignedVaddr,
newEntry.pageStart());
entry = insert(alignedVaddr, newEntry);
}
DPRINTF(TLB, "Miss was serviced.\n");
#endif
}
// Do paging protection checks. // Do paging protection checks.
DPRINTF(TLB, "Entry found with paddr %#x, doing protection checks.\n", entry->paddr); DPRINTF(TLB, "Entry found with paddr %#x, "
"doing protection checks.\n", entry->paddr);
Addr paddr = entry->paddr | (vaddr & (entry->size-1)); Addr paddr = entry->paddr | (vaddr & (entry->size-1));
DPRINTF(TLB, "Translated %#x -> %#x.\n", vaddr, paddr); DPRINTF(TLB, "Translated %#x -> %#x.\n", vaddr, paddr);
req->setPaddr(paddr); req->setPaddr(paddr);
}
} else { } else {
//Use the address which already has segmentation applied. //Use the address which already has segmentation applied.
DPRINTF(TLB, "Paging disabled.\n"); DPRINTF(TLB, "Paging disabled.\n");
@ -665,29 +693,41 @@ TLB::translateAtomic(RequestPtr req, ThreadContext *tc,
Fault Fault
DTB::translateAtomic(RequestPtr req, ThreadContext *tc, bool write) DTB::translateAtomic(RequestPtr req, ThreadContext *tc, bool write)
{ {
return TLB::translateAtomic<FakeDTLBFault>(req, tc, write, false); bool delayedResponse;
return TLB::translate(req, tc, NULL, write,
false, delayedResponse, false);
} }
void void
DTB::translateTiming(RequestPtr req, ThreadContext *tc, DTB::translateTiming(RequestPtr req, ThreadContext *tc,
Translation *translation, bool write) Translation *translation, bool write)
{ {
bool delayedResponse;
assert(translation); assert(translation);
translation->finish(translateAtomic(req, tc, write), req, tc, write); Fault fault = TLB::translate(req, tc, translation,
write, false, delayedResponse, true);
if (!delayedResponse)
translation->finish(fault, req, tc, write);
} }
Fault Fault
ITB::translateAtomic(RequestPtr req, ThreadContext *tc) ITB::translateAtomic(RequestPtr req, ThreadContext *tc)
{ {
return TLB::translateAtomic<FakeITLBFault>(req, tc, false, true); bool delayedResponse;
return TLB::translate(req, tc, NULL, false,
true, delayedResponse, false);
} }
void void
ITB::translateTiming(RequestPtr req, ThreadContext *tc, ITB::translateTiming(RequestPtr req, ThreadContext *tc,
Translation *translation) Translation *translation)
{ {
bool delayedResponse;
assert(translation); assert(translation);
translation->finish(translateAtomic(req, tc), req, tc, false); Fault fault = TLB::translate(req, tc, translation,
false, true, delayedResponse, true);
if (!delayedResponse)
translation->finish(fault, req, tc, false);
} }
#if FULL_SYSTEM #if FULL_SYSTEM

View file

@ -87,8 +87,7 @@ namespace X86ISA
class TLB : public BaseTLB class TLB : public BaseTLB
{ {
protected: protected:
friend class FakeITLBFault; friend class Walker;
friend class FakeDTLBFault;
typedef std::list<TlbEntry *> EntryList; typedef std::list<TlbEntry *> EntryList;
@ -118,8 +117,6 @@ namespace X86ISA
protected: protected:
Walker * walker; Walker * walker;
void walk(ThreadContext * _tc, Addr vaddr, bool write, bool execute);
#endif #endif
public: public:
@ -137,15 +134,13 @@ namespace X86ISA
EntryList freeList; EntryList freeList;
EntryList entryList; EntryList entryList;
template<class TlbFault> Fault translate(RequestPtr req, ThreadContext *tc,
Fault translateAtomic(RequestPtr req, ThreadContext *tc, Translation *translation, bool write, bool execute,
bool write, bool execute); bool &delayedResponse, bool timing);
void translateTiming(RequestPtr req, ThreadContext *tc,
Translation *translation, bool write, bool execute);
public: public:
void insert(Addr vpn, TlbEntry &entry); TlbEntry * insert(Addr vpn, TlbEntry &entry);
// Checkpointing // Checkpointing
virtual void serialize(std::ostream &os); virtual void serialize(std::ostream &os);