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:
@@ -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);
|
VAddr vaddr(pc);
|
||||||
} else {
|
dynamic_cast<TLB *>(tc->getITBPtr())->insert(vaddr.page(), *entry);
|
||||||
VAddr vaddr(pc);
|
|
||||||
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
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
panic_if(FullSystem, "acc not implemented for MIPS FS!");
|
||||||
if (FullSystem)
|
return context()->getProcessPtr()->pTable->lookup(va) != nullptr;
|
||||||
panic("acc not implemented for MIPS FS!");
|
|
||||||
else
|
|
||||||
return context()->getProcessPtr()->pTable->lookup(va, entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -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.
|
panic_if(FullSystem, "acc not implemented for POWER FS!");
|
||||||
if (FullSystem)
|
return context()->getProcessPtr()->pTable->lookup(va) != nullptr;
|
||||||
panic("acc not implemented for POWER FS!");
|
|
||||||
else
|
|
||||||
return context()->getProcessPtr()->pTable->lookup(va, entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -629,49 +629,46 @@ 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);
|
|
||||||
|
|
||||||
// Grab fields used during instruction translation to figure out
|
Addr alignedvaddr = p->pTable->pageAlign(vaddr);
|
||||||
// which context to use.
|
|
||||||
uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA);
|
|
||||||
|
|
||||||
// Inside a VM, a real address is the address that guest OS would
|
// Grab fields used during instruction translation to figure out
|
||||||
// interpret to be a physical address. To map to the physical address,
|
// which context to use.
|
||||||
// it still needs to undergo a translation. The instruction
|
uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA);
|
||||||
// translation code in the SPARC ITLB code assumes that the context is
|
|
||||||
// zero (kernel-level) if real addressing is being used.
|
|
||||||
bool is_real_address = !bits(tlbdata, 4);
|
|
||||||
|
|
||||||
// The SPARC ITLB code assumes that traps are executed in context
|
// Inside a VM, a real address is the address that guest OS would
|
||||||
// zero so we carry that assumption through here.
|
// interpret to be a physical address. To map to the physical address,
|
||||||
bool trapped = bits(tlbdata, 18, 16) > 0;
|
// it still needs to undergo a translation. The instruction
|
||||||
|
// translation code in the SPARC ITLB code assumes that the context is
|
||||||
|
// zero (kernel-level) if real addressing is being used.
|
||||||
|
bool is_real_address = !bits(tlbdata, 4);
|
||||||
|
|
||||||
// The primary context acts as a PASID. It allows the MMU to
|
// The SPARC ITLB code assumes that traps are executed in context
|
||||||
// distinguish between virtual addresses that would alias to the
|
// zero so we carry that assumption through here.
|
||||||
// same physical address (if two or more processes shared the same
|
bool trapped = bits(tlbdata, 18, 16) > 0;
|
||||||
// virtual address mapping).
|
|
||||||
int primary_context = bits(tlbdata, 47, 32);
|
|
||||||
|
|
||||||
// The partition id distinguishes between virtualized environments.
|
// The primary context acts as a PASID. It allows the MMU to
|
||||||
int const partition_id = 0;
|
// distinguish between virtual addresses that would alias to the
|
||||||
|
// same physical address (if two or more processes shared the same
|
||||||
|
// virtual address mapping).
|
||||||
|
int primary_context = bits(tlbdata, 47, 32);
|
||||||
|
|
||||||
// Given the assumptions in the translateInst code in the SPARC ITLB,
|
// The partition id distinguishes between virtualized environments.
|
||||||
// the logic works out to the following for the context.
|
int const partition_id = 0;
|
||||||
int context_id = (is_real_address || trapped) ? 0 : primary_context;
|
|
||||||
|
|
||||||
// Insert the TLB entry.
|
// Given the assumptions in the translateInst code in the SPARC ITLB,
|
||||||
// The entry specifying whether the address is "real" is set to
|
// the logic works out to the following for the context.
|
||||||
// false for syscall emulation mode regardless of whether the
|
int context_id = (is_real_address || trapped) ? 0 : primary_context;
|
||||||
// address is real in preceding code. Not sure sure that this is
|
|
||||||
// correct, but also not sure if it matters at all.
|
// Insert the TLB entry.
|
||||||
dynamic_cast<TLB *>(tc->getITBPtr())->
|
// The entry specifying whether the address is "real" is set to
|
||||||
insert(alignedvaddr, partition_id, context_id, false, entry.pte);
|
// false for syscall emulation mode regardless of whether the
|
||||||
}
|
// address is real in preceding code. Not sure sure that this is
|
||||||
|
// correct, but also not sure if it matters at all.
|
||||||
|
dynamic_cast<TLB *>(tc->getITBPtr())->
|
||||||
|
insert(alignedvaddr, partition_id, context_id, false, entry->pte);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -683,83 +680,78 @@ 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);
|
|
||||||
|
|
||||||
// Grab fields used during data translation to figure out
|
Addr alignedvaddr = p->pTable->pageAlign(vaddr);
|
||||||
// which context to use.
|
|
||||||
uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA);
|
|
||||||
|
|
||||||
// The primary context acts as a PASID. It allows the MMU to
|
// Grab fields used during data translation to figure out
|
||||||
// distinguish between virtual addresses that would alias to the
|
// which context to use.
|
||||||
// same physical address (if two or more processes shared the same
|
uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA);
|
||||||
// virtual address mapping). There's a secondary context used in the
|
|
||||||
// DTLB translation code, but it should __probably__ be zero for
|
|
||||||
// syscall emulation code. (The secondary context is used by Solaris
|
|
||||||
// to allow kernel privilege code to access user space code:
|
|
||||||
// [ISBN 0-13-022496-0]:PG199.)
|
|
||||||
int primary_context = bits(tlbdata, 47, 32);
|
|
||||||
|
|
||||||
// "Hyper-Privileged Mode" is in use. There are three main modes of
|
// The primary context acts as a PASID. It allows the MMU to
|
||||||
// operation for Sparc: Hyper-Privileged Mode, Privileged Mode, and
|
// distinguish between virtual addresses that would alias to the
|
||||||
// User Mode.
|
// same physical address (if two or more processes shared the same
|
||||||
int hpriv = bits(tlbdata, 0);
|
// virtual address mapping). There's a secondary context used in the
|
||||||
|
// DTLB translation code, but it should __probably__ be zero for
|
||||||
|
// syscall emulation code. (The secondary context is used by Solaris
|
||||||
|
// to allow kernel privilege code to access user space code:
|
||||||
|
// [ISBN 0-13-022496-0]:PG199.)
|
||||||
|
int primary_context = bits(tlbdata, 47, 32);
|
||||||
|
|
||||||
// Reset, Error and Debug state is in use. Something horrible has
|
// "Hyper-Privileged Mode" is in use. There are three main modes of
|
||||||
// happened or the system is operating in Reset Mode.
|
// operation for Sparc: Hyper-Privileged Mode, Privileged Mode, and
|
||||||
int red = bits(tlbdata, 1);
|
// User Mode.
|
||||||
|
int hpriv = bits(tlbdata, 0);
|
||||||
|
|
||||||
// Inside a VM, a real address is the address that guest OS would
|
// Reset, Error and Debug state is in use. Something horrible has
|
||||||
// interpret to be a physical address. To map to the physical address,
|
// happened or the system is operating in Reset Mode.
|
||||||
// it still needs to undergo a translation. The instruction
|
int red = bits(tlbdata, 1);
|
||||||
// translation code in the SPARC ITLB code assumes that the context is
|
|
||||||
// zero (kernel-level) if real addressing is being used.
|
|
||||||
int is_real_address = !bits(tlbdata, 5);
|
|
||||||
|
|
||||||
// Grab the address space identifier register from the thread context.
|
// Inside a VM, a real address is the address that guest OS would
|
||||||
// XXX: Inspecting how setMiscReg and setMiscRegNoEffect behave for
|
// interpret to be a physical address. To map to the physical address,
|
||||||
// MISCREG_ASI causes me to think that the ASI register implementation
|
// it still needs to undergo a translation. The instruction
|
||||||
// might be bugged. The NoEffect variant changes the ASI register
|
// translation code in the SPARC ITLB code assumes that the context is
|
||||||
// value in the architectural state while the normal variant changes
|
// zero (kernel-level) if real addressing is being used.
|
||||||
// the context field in the thread context's currently decoded request
|
int is_real_address = !bits(tlbdata, 5);
|
||||||
// but does not directly affect the ASI register value in the
|
|
||||||
// architectural state. The ASI values and the context field in the
|
|
||||||
// request packet seem to have completely different uses.
|
|
||||||
MiscReg reg_asi = tc->readMiscRegNoEffect(MISCREG_ASI);
|
|
||||||
ASI asi = static_cast<ASI>(reg_asi);
|
|
||||||
|
|
||||||
// The SPARC DTLB code assumes that traps are executed in context
|
// Grab the address space identifier register from the thread context.
|
||||||
// zero if the asi value is ASI_IMPLICIT (which is 0x0). There's also
|
// XXX: Inspecting how setMiscReg and setMiscRegNoEffect behave for
|
||||||
// an assumption that the nucleus address space is being used, but
|
// MISCREG_ASI causes me to think that the ASI register implementation
|
||||||
// the context is the relevant issue since we need to pass it to TLB.
|
// might be bugged. The NoEffect variant changes the ASI register
|
||||||
bool trapped = bits(tlbdata, 18, 16) > 0;
|
// value in the architectural state while the normal variant changes
|
||||||
|
// the context field in the thread context's currently decoded request
|
||||||
|
// but does not directly affect the ASI register value in the
|
||||||
|
// architectural state. The ASI values and the context field in the
|
||||||
|
// request packet seem to have completely different uses.
|
||||||
|
MiscReg reg_asi = tc->readMiscRegNoEffect(MISCREG_ASI);
|
||||||
|
ASI asi = static_cast<ASI>(reg_asi);
|
||||||
|
|
||||||
// Given the assumptions in the translateData code in the SPARC DTLB,
|
// The SPARC DTLB code assumes that traps are executed in context
|
||||||
// the logic works out to the following for the context.
|
// zero if the asi value is ASI_IMPLICIT (which is 0x0). There's also
|
||||||
int context_id = ((!hpriv && !red && is_real_address) ||
|
// an assumption that the nucleus address space is being used, but
|
||||||
asiIsReal(asi) ||
|
// the context is the relevant issue since we need to pass it to TLB.
|
||||||
(trapped && asi == ASI_IMPLICIT))
|
bool trapped = bits(tlbdata, 18, 16) > 0;
|
||||||
? 0 : primary_context;
|
|
||||||
|
|
||||||
// The partition id distinguishes between virtualized environments.
|
// Given the assumptions in the translateData code in the SPARC DTLB,
|
||||||
int const partition_id = 0;
|
// the logic works out to the following for the context.
|
||||||
|
int context_id = ((!hpriv && !red && is_real_address) ||
|
||||||
|
asiIsReal(asi) ||
|
||||||
|
(trapped && asi == ASI_IMPLICIT))
|
||||||
|
? 0 : primary_context;
|
||||||
|
|
||||||
// Insert the TLB entry.
|
// The partition id distinguishes between virtualized environments.
|
||||||
// The entry specifying whether the address is "real" is set to
|
int const partition_id = 0;
|
||||||
// false for syscall emulation mode regardless of whether the
|
|
||||||
// address is real in preceding code. Not sure sure that this is
|
// Insert the TLB entry.
|
||||||
// correct, but also not sure if it matters at all.
|
// The entry specifying whether the address is "real" is set to
|
||||||
dynamic_cast<TLB *>(tc->getDTBPtr())->
|
// false for syscall emulation mode regardless of whether the
|
||||||
insert(alignedvaddr, partition_id, context_id, false, entry.pte);
|
// address is real in preceding code. Not sure sure that this is
|
||||||
}
|
// correct, but also not sure if it matters at all.
|
||||||
|
dynamic_cast<TLB *>(tc->getDTBPtr())->
|
||||||
|
insert(alignedvaddr, partition_id, context_id, false, entry->pte);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr,
|
if (newEntry) {
|
||||||
newEntry.pageStart());
|
DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr,
|
||||||
|
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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user