summaryrefslogtreecommitdiff
path: root/src/arch/x86/tlb.cc
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2009-02-25 10:16:21 -0800
committerGabe Black <gblack@eecs.umich.edu>2009-02-25 10:16:21 -0800
commit40fdba2454c219902db7ad1abd28593de8611c2b (patch)
tree79369b7e2d1caae9f0accd45e6f9a0f53c1002f2 /src/arch/x86/tlb.cc
parent6ed47e94644f854baa33d1e9f367cc9eebd99abf (diff)
downloadgem5-40fdba2454c219902db7ad1abd28593de8611c2b.tar.xz
X86: Make the X86 TLB take advantage of delayed translations, and get rid of the fake TLB miss faults.
Diffstat (limited to 'src/arch/x86/tlb.cc')
-rw-r--r--src/arch/x86/tlb.cc86
1 files changed, 63 insertions, 23 deletions
diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc
index a34922b44..3962cd607 100644
--- a/src/arch/x86/tlb.cc
+++ b/src/arch/x86/tlb.cc
@@ -72,6 +72,9 @@
#if FULL_SYSTEM
#include "arch/x86/pagetable_walker.hh"
+#else
+#include "mem/page_table.hh"
+#include "sim/process.hh"
#endif
namespace X86ISA {
@@ -90,7 +93,7 @@ TLB::TLB(const Params *p) : BaseTLB(p), configAddress(0), size(p->size)
#endif
}
-void
+TlbEntry *
TLB::insert(Addr vpn, TlbEntry &entry)
{
//TODO Deal with conflicting entries
@@ -106,6 +109,7 @@ TLB::insert(Addr vpn, TlbEntry &entry)
*newEntry = entry;
newEntry->vaddr = vpn;
entryList.push_front(newEntry);
+ return newEntry;
}
TLB::EntryList::iterator
@@ -138,14 +142,6 @@ TLB::lookup(Addr va, bool update_lru)
return *entry;
}
-#if FULL_SYSTEM
-void
-TLB::walk(ThreadContext * _tc, Addr vaddr, bool write, bool execute)
-{
- walker->start(_tc, vaddr, write, execute);
-}
-#endif
-
void
TLB::invalidateAll()
{
@@ -188,11 +184,12 @@ TLB::demapPage(Addr va, uint64_t asn)
}
}
-template<class TlbFault>
Fault
-TLB::translateAtomic(RequestPtr req, ThreadContext *tc,
- bool write, bool execute)
+TLB::translate(RequestPtr req, ThreadContext *tc,
+ Translation *translation, bool write, bool execute,
+ bool &delayedResponse, bool timing)
{
+ delayedResponse = false;
Addr vaddr = req->getVaddr();
DPRINTF(TLB, "Translating vaddr %#x.\n", vaddr);
uint32_t flags = req->getFlags();
@@ -617,14 +614,45 @@ TLB::translateAtomic(RequestPtr req, ThreadContext *tc,
// The vaddr already has the segment base applied.
TlbEntry *entry = lookup(vaddr);
if (!entry) {
- return new TlbFault(vaddr, write, execute);
- } else {
- // Do paging protection checks.
- DPRINTF(TLB, "Entry found with paddr %#x, doing protection checks.\n", entry->paddr);
- Addr paddr = entry->paddr | (vaddr & (entry->size-1));
- DPRINTF(TLB, "Translated %#x -> %#x.\n", vaddr, paddr);
- req->setPaddr(paddr);
+#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 {
+ 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.
+ DPRINTF(TLB, "Entry found with paddr %#x, "
+ "doing protection checks.\n", entry->paddr);
+ Addr paddr = entry->paddr | (vaddr & (entry->size-1));
+ DPRINTF(TLB, "Translated %#x -> %#x.\n", vaddr, paddr);
+ req->setPaddr(paddr);
} else {
//Use the address which already has segmentation applied.
DPRINTF(TLB, "Paging disabled.\n");
@@ -665,29 +693,41 @@ TLB::translateAtomic(RequestPtr req, ThreadContext *tc,
Fault
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
DTB::translateTiming(RequestPtr req, ThreadContext *tc,
Translation *translation, bool write)
{
+ bool delayedResponse;
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
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
ITB::translateTiming(RequestPtr req, ThreadContext *tc,
Translation *translation)
{
+ bool delayedResponse;
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