arch, mem: Make the page table lookup function return a pointer.

This avoids having a copy in the lookup function itself, and the
declaration of a lot of temporary TLB entry pointers in callers. The
gpu TLB seems to have had the most dependence on the original signature
of the lookup function, partially because it was relying on a somewhat
unsafe copy to a TLB entry using a base class pointer type.

Change-Id: I8b1cf494468163deee000002d243541657faf57f
Reviewed-on: https://gem5-review.googlesource.com/7343
Reviewed-by: Gabe Black <gabeblack@google.com>
Maintainer: Gabe Black <gabeblack@google.com>
This commit is contained in:
Gabe Black
2018-01-05 15:01:00 -08:00
parent b1ade08b2d
commit 2a15bfd79c
13 changed files with 177 additions and 217 deletions

View File

@@ -196,14 +196,11 @@ ItbPageFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
} }
Process *p = tc->getProcessPtr(); Process *p = tc->getProcessPtr();
TlbEntry entry; TlbEntry *entry = p->pTable->lookup(pc);
bool success = p->pTable->lookup(pc, entry); panic_if(!entry, "Tried to execute unmapped address %#x.\n", pc);
if (!success) {
panic("Tried to execute unmapped address %#x.\n", pc);
} else {
VAddr vaddr(pc); VAddr vaddr(pc);
dynamic_cast<TLB *>(tc->getITBPtr())->insert(vaddr.page(), entry); dynamic_cast<TLB *>(tc->getITBPtr())->insert(vaddr.page(), *entry);
}
} }
void void
@@ -215,17 +212,11 @@ NDtbMissFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
} }
Process *p = tc->getProcessPtr(); Process *p = tc->getProcessPtr();
TlbEntry entry; TlbEntry *entry = p->pTable->lookup(vaddr);
bool success = p->pTable->lookup(vaddr, entry); if (!entry && p->fixupStackFault(vaddr))
if (!success) { entry = p->pTable->lookup(vaddr);
if (p->fixupStackFault(vaddr)) panic_if(!entry, "Tried to access unmapped address %#x.\n", (Addr)vaddr);
success = p->pTable->lookup(vaddr, entry); dynamic_cast<TLB *>(tc->getDTBPtr())->insert(vaddr.page(), *entry);
}
if (!success) {
panic("Tried to access unmapped address %#x.\n", (Addr)vaddr);
} else {
dynamic_cast<TLB *>(tc->getDTBPtr())->insert(vaddr.page(), entry);
}
} }
} // namespace AlphaISA } // namespace AlphaISA

View File

@@ -186,12 +186,9 @@ RemoteGDB::acc(Addr va, size_t len)
DPRINTF(GDBAcc, "acc: %#x mapping is valid\n", va); DPRINTF(GDBAcc, "acc: %#x mapping is valid\n", va);
return true; return true;
} else { } else {
TlbEntry entry; // Check to make sure the first byte is mapped into the processes
//Check to make sure the first byte is mapped into the processes address // address space.
//space. return context()->getProcessPtr()->pTable->lookup(va) != nullptr;
if (context()->getProcessPtr()->pTable->lookup(va, entry))
return true;
return false;
} }
} }

View File

@@ -162,13 +162,10 @@ RemoteGDB::RemoteGDB(System *_system, ThreadContext *tc, int _port)
bool bool
RemoteGDB::acc(Addr va, size_t len) RemoteGDB::acc(Addr va, size_t len)
{ {
TlbEntry entry;
// Check to make sure the first byte is mapped into the processes address // Check to make sure the first byte is mapped into the processes address
// space. // space.
if (FullSystem) panic_if(FullSystem, "acc not implemented for MIPS FS!");
panic("acc not implemented for MIPS FS!"); return context()->getProcessPtr()->pTable->lookup(va) != nullptr;
else
return context()->getProcessPtr()->pTable->lookup(va, entry);
} }
void void

View File

@@ -162,16 +162,13 @@ RemoteGDB::RemoteGDB(System *_system, ThreadContext *tc, int _port)
bool bool
RemoteGDB::acc(Addr va, size_t len) RemoteGDB::acc(Addr va, size_t len)
{ {
TlbEntry entry;
// Check to make sure the first byte is mapped into the processes address // Check to make sure the first byte is mapped into the processes address
// space. At the time of this writing, the acc() check is used when // space. At the time of this writing, the acc() check is used when
// processing the MemR/MemW packets before actually asking the translating // processing the MemR/MemW packets before actually asking the translating
// port proxy to read/writeBlob. I (bgs) am not convinced the first byte // port proxy to read/writeBlob. I (bgs) am not convinced the first byte
// check is enough. // check is enough.
if (FullSystem) panic_if(FullSystem, "acc not implemented for POWER FS!");
panic("acc not implemented for POWER FS!"); return context()->getProcessPtr()->pTable->lookup(va) != nullptr;
else
return context()->getProcessPtr()->pTable->lookup(va, entry);
} }
void void

View File

@@ -156,11 +156,8 @@ RemoteGDB::RemoteGDB(System *_system, ThreadContext *tc, int _port)
bool bool
RemoteGDB::acc(Addr va, size_t len) RemoteGDB::acc(Addr va, size_t len)
{ {
TlbEntry entry; panic_if(FullSystem, "acc not implemented for RISCV FS!");
if (FullSystem) return context()->getProcessPtr()->pTable->lookup(va) != nullptr;
panic("acc not implemented for RISCV FS!");
else
return context()->getProcessPtr()->pTable->lookup(va, entry);
} }
void void

View File

@@ -629,11 +629,9 @@ FastInstructionAccessMMUMiss::invoke(ThreadContext *tc,
} }
Process *p = tc->getProcessPtr(); Process *p = tc->getProcessPtr();
TlbEntry entry; TlbEntry *entry = p->pTable->lookup(vaddr);
bool success = p->pTable->lookup(vaddr, entry); panic_if(!entry, "Tried to execute unmapped address %#x.\n", vaddr);
if (!success) {
panic("Tried to execute unmapped address %#x.\n", vaddr);
} else {
Addr alignedvaddr = p->pTable->pageAlign(vaddr); Addr alignedvaddr = p->pTable->pageAlign(vaddr);
// Grab fields used during instruction translation to figure out // Grab fields used during instruction translation to figure out
@@ -670,8 +668,7 @@ FastInstructionAccessMMUMiss::invoke(ThreadContext *tc,
// address is real in preceding code. Not sure sure that this is // address is real in preceding code. Not sure sure that this is
// correct, but also not sure if it matters at all. // correct, but also not sure if it matters at all.
dynamic_cast<TLB *>(tc->getITBPtr())-> dynamic_cast<TLB *>(tc->getITBPtr())->
insert(alignedvaddr, partition_id, context_id, false, entry.pte); insert(alignedvaddr, partition_id, context_id, false, entry->pte);
}
} }
void void
@@ -683,15 +680,11 @@ FastDataAccessMMUMiss::invoke(ThreadContext *tc, const StaticInstPtr &inst)
} }
Process *p = tc->getProcessPtr(); Process *p = tc->getProcessPtr();
TlbEntry entry; TlbEntry *entry = p->pTable->lookup(vaddr);
bool success = p->pTable->lookup(vaddr, entry); if (!entry && p->fixupStackFault(vaddr))
if (!success) { entry = p->pTable->lookup(vaddr);
if (p->fixupStackFault(vaddr)) panic_if(!entry, "Tried to access unmapped address %#x.\n", 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); Addr alignedvaddr = p->pTable->pageAlign(vaddr);
// Grab fields used during data translation to figure out // Grab fields used during data translation to figure out
@@ -758,8 +751,7 @@ FastDataAccessMMUMiss::invoke(ThreadContext *tc, const StaticInstPtr &inst)
// address is real in preceding code. Not sure sure that this is // address is real in preceding code. Not sure sure that this is
// correct, but also not sure if it matters at all. // correct, but also not sure if it matters at all.
dynamic_cast<TLB *>(tc->getDTBPtr())-> dynamic_cast<TLB *>(tc->getDTBPtr())->
insert(alignedvaddr, partition_id, context_id, false, entry.pte); insert(alignedvaddr, partition_id, context_id, false, entry->pte);
}
} }
void void

View File

@@ -163,16 +163,11 @@ RemoteGDB::acc(Addr va, size_t len)
// from va to va + len have valid page map entries. Not // from va to va + len have valid page map entries. Not
// sure how this will work for other OSes or in general. // sure how this will work for other OSes or in general.
if (FullSystem) { if (FullSystem) {
if (va) return va != 0;
return true;
return false;
} else { } else {
TlbEntry entry;
// Check to make sure the first byte is mapped into the processes // Check to make sure the first byte is mapped into the processes
// address space. // address space.
if (context()->getProcessPtr()->pTable->lookup(va, entry)) return context()->getProcessPtr()->pTable->lookup(va) != nullptr;
return true;
return false;
} }
} }

View File

@@ -88,8 +88,7 @@ RemoteGDB::acc(Addr va, size_t len)
BaseTLB::Read); BaseTLB::Read);
return fault == NoFault; return fault == NoFault;
} else { } else {
TlbEntry entry; return context()->getProcessPtr()->pTable->lookup(va) != nullptr;
return context()->getProcessPtr()->pTable->lookup(va, entry);
} }
} }

View File

@@ -94,7 +94,7 @@ TLB::evictLRU()
} }
TlbEntry * TlbEntry *
TLB::insert(Addr vpn, TlbEntry &entry) TLB::insert(Addr vpn, const TlbEntry &entry)
{ {
// If somebody beat us to it, just use that existing entry. // If somebody beat us to it, just use that existing entry.
TlbEntry *newEntry = trie.lookup(vpn); TlbEntry *newEntry = trie.lookup(vpn);
@@ -357,23 +357,22 @@ TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation,
assert(entry); assert(entry);
} else { } else {
Process *p = tc->getProcessPtr(); Process *p = tc->getProcessPtr();
TlbEntry newEntry; TlbEntry *newEntry = p->pTable->lookup(vaddr);
bool success = p->pTable->lookup(vaddr, newEntry); if (!newEntry && mode != Execute) {
if (!success && mode != Execute) {
// Check if we just need to grow the stack. // Check if we just need to grow the stack.
if (p->fixupStackFault(vaddr)) { if (p->fixupStackFault(vaddr)) {
// If we did, lookup the entry for the new page. // If we did, lookup the entry for the new page.
success = p->pTable->lookup(vaddr, newEntry); newEntry = p->pTable->lookup(vaddr);
} }
} }
if (!success) { if (!newEntry) {
return std::make_shared<PageFault>(vaddr, true, mode, return std::make_shared<PageFault>(vaddr, true, mode,
true, false); true, false);
} else { } else {
Addr alignedVaddr = p->pTable->pageAlign(vaddr); Addr alignedVaddr = p->pTable->pageAlign(vaddr);
DPRINTF(TLB, "Mapping %#x to %#x\n", alignedVaddr, DPRINTF(TLB, "Mapping %#x to %#x\n", alignedVaddr,
newEntry.pageStart()); newEntry->pageStart());
entry = insert(alignedVaddr, newEntry); entry = insert(alignedVaddr, *newEntry);
} }
DPRINTF(TLB, "Miss was serviced.\n"); DPRINTF(TLB, "Miss was serviced.\n");
} }

View File

@@ -144,7 +144,7 @@ namespace X86ISA
Fault finalizePhysical(RequestPtr req, ThreadContext *tc, Fault finalizePhysical(RequestPtr req, ThreadContext *tc,
Mode mode) const override; Mode mode) const override;
TlbEntry * insert(Addr vpn, TlbEntry &entry); TlbEntry *insert(Addr vpn, const TlbEntry &entry);
/* /*
* Function to register Stats * Function to register Stats

View File

@@ -808,31 +808,31 @@ namespace X86ISA
"at pc %#x.\n", vaddr, tc->instAddr()); "at pc %#x.\n", vaddr, tc->instAddr());
Process *p = tc->getProcessPtr(); Process *p = tc->getProcessPtr();
GpuTlbEntry newEntry; TlbEntry *newEntry = p->pTable->lookup(vaddr);
bool success = p->pTable->lookup(vaddr, newEntry);
if (!success && mode != BaseTLB::Execute) { if (!newEntry && mode != BaseTLB::Execute) {
// penalize a "page fault" more // penalize a "page fault" more
if (timing) { if (timing)
latency += missLatency2; latency += missLatency2;
}
if (p->fixupStackFault(vaddr)) if (p->fixupStackFault(vaddr))
success = p->pTable->lookup(vaddr, newEntry); newEntry = p->pTable->lookup(vaddr);
} }
if (!success) { if (!newEntry) {
return std::make_shared<PageFault>(vaddr, true, return std::make_shared<PageFault>(vaddr, true,
mode, true, mode, true,
false); false);
} else { } else {
newEntry.valid = success;
Addr alignedVaddr = p->pTable->pageAlign(vaddr); Addr alignedVaddr = p->pTable->pageAlign(vaddr);
DPRINTF(GPUTLB, "Mapping %#x to %#x\n", DPRINTF(GPUTLB, "Mapping %#x to %#x\n",
alignedVaddr, newEntry.pageStart()); alignedVaddr, newEntry->pageStart());
entry = insert(alignedVaddr, newEntry); GpuTlbEntry gpuEntry;
*(TlbEntry *)&gpuEntry = *newEntry;
gpuEntry.valid = true;
entry = insert(alignedVaddr, gpuEntry);
} }
DPRINTF(GPUTLB, "Miss was serviced.\n"); DPRINTF(GPUTLB, "Miss was serviced.\n");
@@ -1330,25 +1330,27 @@ namespace X86ISA
safe_cast<TranslationState*>(pkt->senderState); safe_cast<TranslationState*>(pkt->senderState);
Process *p = sender_state->tc->getProcessPtr(); Process *p = sender_state->tc->getProcessPtr();
TlbEntry newEntry;
Addr vaddr = pkt->req->getVaddr(); Addr vaddr = pkt->req->getVaddr();
#ifndef NDEBUG #ifndef NDEBUG
Addr alignedVaddr = p->pTable->pageAlign(vaddr); Addr alignedVaddr = p->pTable->pageAlign(vaddr);
assert(alignedVaddr == virtPageAddr); assert(alignedVaddr == virtPageAddr);
#endif #endif
bool success; TlbEntry *newEntry = p->pTable->lookup(vaddr);
success = p->pTable->lookup(vaddr, newEntry); if (!newEntry && sender_state->tlbMode != BaseTLB::Execute &&
if (!success && sender_state->tlbMode != BaseTLB::Execute) { p->fixupStackFault(vaddr)) {
if (p->fixupStackFault(vaddr)) { newEntry = p->pTable->lookup(vaddr);
success = p->pTable->lookup(vaddr, newEntry);
}
} }
if (newEntry) {
DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr, DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr,
newEntry.pageStart()); newEntry->pageStart());
sender_state->tlbEntry = sender_state->tlbEntry =
new GpuTlbEntry(0, newEntry.vaddr, newEntry.paddr, success); new GpuTlbEntry(0, newEntry->vaddr, newEntry->paddr, true);
} else {
sender_state->tlbEntry =
new GpuTlbEntry(0, 0, 0, false);
}
handleTranslationReturn(virtPageAddr, TLB_MISS, pkt); handleTranslationReturn(virtPageAddr, TLB_MISS, pkt);
} else if (outcome == MISS_RETURN) { } else if (outcome == MISS_RETURN) {
@@ -1524,7 +1526,6 @@ namespace X86ISA
virt_page_addr); virt_page_addr);
Process *p = tc->getProcessPtr(); Process *p = tc->getProcessPtr();
TlbEntry newEntry;
Addr vaddr = pkt->req->getVaddr(); Addr vaddr = pkt->req->getVaddr();
#ifndef NDEBUG #ifndef NDEBUG
@@ -1532,10 +1533,10 @@ namespace X86ISA
assert(alignedVaddr == virt_page_addr); assert(alignedVaddr == virt_page_addr);
#endif #endif
bool success = p->pTable->lookup(vaddr, newEntry); TlbEntry *newEntry = p->pTable->lookup(vaddr);
if (!success && sender_state->tlbMode != BaseTLB::Execute) { if (!newEntry && sender_state->tlbMode != BaseTLB::Execute &&
if (p->fixupStackFault(vaddr)) p->fixupStackFault(vaddr)) {
success = p->pTable->lookup(vaddr, newEntry); newEntry = p->pTable->lookup(vaddr);
} }
if (!sender_state->prefetch) { if (!sender_state->prefetch) {
@@ -1544,24 +1545,23 @@ namespace X86ISA
assert(success); assert(success);
DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr, DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr,
newEntry.pageStart()); newEntry->pageStart());
sender_state->tlbEntry = new GpuTlbEntry(0, newEntry.vaddr, sender_state->tlbEntry =
newEntry.paddr, new GpuTlbEntry(0, newEntry->vaddr,
success); newEntry->paddr, success);
} else { } else {
// If this was a prefetch, then do the normal thing if it // If this was a prefetch, then do the normal thing if it
// was a successful translation. Otherwise, send an empty // was a successful translation. Otherwise, send an empty
// TLB entry back so that it can be figured out as empty and // TLB entry back so that it can be figured out as empty and
// handled accordingly. // handled accordingly.
if (success) { if (newEntry) {
DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr, DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr,
newEntry.pageStart()); newEntry->pageStart());
sender_state->tlbEntry = new GpuTlbEntry(0, sender_state->tlbEntry =
newEntry.vaddr, new GpuTlbEntry(0, newEntry->vaddr,
newEntry.paddr, newEntry->paddr, success);
success);
} else { } else {
DPRINTF(GPUPrefetch, "Prefetch failed %#x\n", DPRINTF(GPUPrefetch, "Prefetch failed %#x\n",
alignedVaddr); alignedVaddr);

View File

@@ -146,29 +146,25 @@ EmulationPageTable::isUnmapped(Addr vaddr, int64_t size)
return true; return true;
} }
bool TheISA::TlbEntry *
EmulationPageTable::lookup(Addr vaddr, TheISA::TlbEntry &entry) EmulationPageTable::lookup(Addr vaddr)
{ {
Addr page_addr = pageAlign(vaddr); Addr page_addr = pageAlign(vaddr);
PTableItr iter = pTable.find(page_addr); PTableItr iter = pTable.find(page_addr);
if (iter == pTable.end()) if (iter == pTable.end())
return false; return nullptr;
return iter->second;
entry = *iter->second;
return true;
} }
bool bool
EmulationPageTable::translate(Addr vaddr, Addr &paddr) EmulationPageTable::translate(Addr vaddr, Addr &paddr)
{ {
TheISA::TlbEntry entry; TheISA::TlbEntry *entry = lookup(vaddr);
if (!lookup(vaddr, entry)) { if (!entry) {
DPRINTF(MMU, "Couldn't Translate: %#x\n", vaddr); DPRINTF(MMU, "Couldn't Translate: %#x\n", vaddr);
return false; return false;
} }
paddr = pageOffset(vaddr) + entry.pageStart(); paddr = pageOffset(vaddr) + entry->pageStart();
DPRINTF(MMU, "Translating: %#x->%#x\n", vaddr, paddr); DPRINTF(MMU, "Translating: %#x->%#x\n", vaddr, paddr);
return true; return true;
} }

View File

@@ -121,9 +121,9 @@ class EmulationPageTable : public Serializable
/** /**
* Lookup function * Lookup function
* @param vaddr The virtual address. * @param vaddr The virtual address.
* @return entry The page table entry corresponding to vaddr. * @return The page table entry corresponding to vaddr.
*/ */
virtual bool lookup(Addr vaddr, TheISA::TlbEntry &entry); virtual TheISA::TlbEntry *lookup(Addr vaddr);
/** /**
* Translate function * Translate function