tlb: More fixing of unified TLB
This commit is contained in:
parent
7b5a96f06b
commit
e0de2c3443
|
@ -34,4 +34,10 @@ from BaseTLB import BaseTLB
|
||||||
class AlphaTLB(BaseTLB):
|
class AlphaTLB(BaseTLB):
|
||||||
type = 'AlphaTLB'
|
type = 'AlphaTLB'
|
||||||
cxx_class = 'AlphaISA::TLB'
|
cxx_class = 'AlphaISA::TLB'
|
||||||
size = Param.Int(64, "TLB size")
|
size = Param.Int("TLB size")
|
||||||
|
|
||||||
|
class AlphaDTB(AlphaTLB):
|
||||||
|
size = 64
|
||||||
|
|
||||||
|
class AlphaITB(AlphaTLB):
|
||||||
|
size = 48
|
||||||
|
|
|
@ -607,23 +607,20 @@ TLB::index(bool advance)
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault
|
Fault
|
||||||
TLB::translateAtomic(RequestPtr req, ThreadContext *tc,
|
TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode)
|
||||||
bool write, bool execute)
|
|
||||||
{
|
{
|
||||||
if (execute)
|
if (mode == Execute)
|
||||||
return translateInst(req, tc);
|
return translateInst(req, tc);
|
||||||
else
|
else
|
||||||
return translateData(req, tc, write);
|
return translateData(req, tc, mode == Write);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TLB::translateTiming(RequestPtr req, ThreadContext *tc,
|
TLB::translateTiming(RequestPtr req, ThreadContext *tc,
|
||||||
Translation *translation,
|
Translation *translation, Mode mode)
|
||||||
bool write, bool execute)
|
|
||||||
{
|
{
|
||||||
assert(translation);
|
assert(translation);
|
||||||
translation->finish(translateAtomic(req, tc, write, execute),
|
translation->finish(translateAtomic(req, tc, mode), req, tc, mode);
|
||||||
req, tc, write, execute);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* end namespace AlphaISA */ }
|
/* end namespace AlphaISA */ }
|
||||||
|
|
|
@ -141,11 +141,9 @@ class TLB : public BaseTLB
|
||||||
Fault translateInst(RequestPtr req, ThreadContext *tc);
|
Fault translateInst(RequestPtr req, ThreadContext *tc);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Fault translateAtomic(RequestPtr req, ThreadContext *tc,
|
Fault translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode);
|
||||||
bool write = false, bool execute = false);
|
|
||||||
void translateTiming(RequestPtr req, ThreadContext *tc,
|
void translateTiming(RequestPtr req, ThreadContext *tc,
|
||||||
Translation *translation,
|
Translation *translation, Mode mode);
|
||||||
bool write = false, bool execute = false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace AlphaISA
|
} // namespace AlphaISA
|
||||||
|
|
|
@ -562,22 +562,20 @@ TLB::translateData(RequestPtr req, ThreadContext *tc, bool write)
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault
|
Fault
|
||||||
TLB::translateAtomic(RequestPtr req, ThreadContext *tc,
|
TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode)
|
||||||
bool write, bool execute)
|
|
||||||
{
|
{
|
||||||
if (execute)
|
if (mode == Execute)
|
||||||
return translateInst(req, tc);
|
return translateInst(req, tc);
|
||||||
else
|
else
|
||||||
return translateData(req, tc, write);
|
return translateData(req, tc, mode == Write);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TLB::translateTiming(RequestPtr req, ThreadContext *tc,
|
TLB::translateTiming(RequestPtr req, ThreadContext *tc,
|
||||||
Translation *translation, bool write, bool execute)
|
Translation *translation, Mode mode)
|
||||||
{
|
{
|
||||||
assert(translation);
|
assert(translation);
|
||||||
translation->finish(translateAtomic(req, tc, write, execute),
|
translation->finish(translateAtomic(req, tc, mode), req, tc, mode);
|
||||||
req, tc, write, execute);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -138,10 +138,9 @@ class TLB : public BaseTLB
|
||||||
|
|
||||||
void regStats();
|
void regStats();
|
||||||
|
|
||||||
Fault translateAtomic(RequestPtr req, ThreadContext *tc,
|
Fault translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode);
|
||||||
bool write=false, bool execute=false);
|
|
||||||
void translateTiming(RequestPtr req, ThreadContext *tc,
|
void translateTiming(RequestPtr req, ThreadContext *tc,
|
||||||
Translation *translation, bool write=false, bool execute=false);
|
Translation *translation, Mode mode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Fault translateInst(RequestPtr req, ThreadContext *tc);
|
Fault translateInst(RequestPtr req, ThreadContext *tc);
|
||||||
|
|
|
@ -843,22 +843,20 @@ handleMmuRegAccess:
|
||||||
};
|
};
|
||||||
|
|
||||||
Fault
|
Fault
|
||||||
TLB::translateAtomic(RequestPtr req, ThreadContext *tc,
|
TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode)
|
||||||
bool write, bool execute)
|
|
||||||
{
|
{
|
||||||
if (execute)
|
if (mode == Execute)
|
||||||
return translateInst(req, tc);
|
return translateInst(req, tc);
|
||||||
else
|
else
|
||||||
return translateData(req, tc, write);
|
return translateData(req, tc, mode == Write);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TLB::translateTiming(RequestPtr req, ThreadContext *tc,
|
TLB::translateTiming(RequestPtr req, ThreadContext *tc,
|
||||||
Translation *translation, bool write, bool execute)
|
Translation *translation, Mode mode)
|
||||||
{
|
{
|
||||||
assert(translation);
|
assert(translation);
|
||||||
translation->finish(translateAtomic(req, tc, write, execute),
|
translation->finish(translateAtomic(req, tc, mode), req, tc, mode);
|
||||||
req, tc, write, execute);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
|
|
|
@ -163,10 +163,9 @@ class TLB : public BaseTLB
|
||||||
|
|
||||||
void dumpAll();
|
void dumpAll();
|
||||||
|
|
||||||
Fault translateAtomic(RequestPtr req,
|
Fault translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode);
|
||||||
ThreadContext *tc, bool write=false, bool execute=false);
|
|
||||||
void translateTiming(RequestPtr req, ThreadContext *tc,
|
void translateTiming(RequestPtr req, ThreadContext *tc,
|
||||||
Translation *translation, bool write=false, bool execute=false);
|
Translation *translation, Mode mode);
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
Tick doMmuRegRead(ThreadContext *tc, Packet *pkt);
|
Tick doMmuRegRead(ThreadContext *tc, Packet *pkt);
|
||||||
Tick doMmuRegWrite(ThreadContext *tc, Packet *pkt);
|
Tick doMmuRegWrite(ThreadContext *tc, Packet *pkt);
|
||||||
|
|
|
@ -61,6 +61,7 @@
|
||||||
#include "base/bitunion.hh"
|
#include "base/bitunion.hh"
|
||||||
#include "base/misc.hh"
|
#include "base/misc.hh"
|
||||||
#include "sim/faults.hh"
|
#include "sim/faults.hh"
|
||||||
|
#include "sim/tlb.hh"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -331,16 +332,16 @@ namespace X86ISA
|
||||||
X86Fault("Page-Fault", "#PF", 14, _errorCode), addr(_addr)
|
X86Fault("Page-Fault", "#PF", 14, _errorCode), addr(_addr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
PageFault(Addr _addr, bool present, bool write,
|
PageFault(Addr _addr, bool present, BaseTLB::Mode mode,
|
||||||
bool user, bool reserved, bool fetch) :
|
bool user, bool reserved) :
|
||||||
X86Fault("Page-Fault", "#PF", 14, 0), addr(_addr)
|
X86Fault("Page-Fault", "#PF", 14, 0), addr(_addr)
|
||||||
{
|
{
|
||||||
PageFaultErrorCode code = 0;
|
PageFaultErrorCode code = 0;
|
||||||
code.present = present;
|
code.present = present;
|
||||||
code.write = write;
|
code.write = (mode == BaseTLB::Write);
|
||||||
code.user = user;
|
code.user = user;
|
||||||
code.reserved = reserved;
|
code.reserved = reserved;
|
||||||
code.fetch = fetch;
|
code.fetch = (mode == BaseTLB::Execute);
|
||||||
errorCode = code;
|
errorCode = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,7 @@ Walker::doNext(PacketPtr &write)
|
||||||
bool uncacheable = pte.pcd;
|
bool uncacheable = pte.pcd;
|
||||||
Addr nextRead = 0;
|
Addr nextRead = 0;
|
||||||
bool doWrite = false;
|
bool doWrite = false;
|
||||||
bool badNX = pte.nx && execute && enableNX;
|
bool badNX = pte.nx && mode == BaseTLB::Write && enableNX;
|
||||||
switch(state) {
|
switch(state) {
|
||||||
case LongPML4:
|
case LongPML4:
|
||||||
DPRINTF(PageTableWalker,
|
DPRINTF(PageTableWalker,
|
||||||
|
@ -329,14 +329,13 @@ Walker::doNext(PacketPtr &write)
|
||||||
|
|
||||||
Fault
|
Fault
|
||||||
Walker::start(ThreadContext * _tc, BaseTLB::Translation *_translation,
|
Walker::start(ThreadContext * _tc, BaseTLB::Translation *_translation,
|
||||||
RequestPtr _req, bool _write, bool _execute)
|
RequestPtr _req, BaseTLB::Mode _mode)
|
||||||
{
|
{
|
||||||
assert(state == Ready);
|
assert(state == Ready);
|
||||||
tc = _tc;
|
tc = _tc;
|
||||||
req = _req;
|
req = _req;
|
||||||
Addr vaddr = req->getVaddr();
|
Addr vaddr = req->getVaddr();
|
||||||
execute = _execute;
|
mode = _mode;
|
||||||
write = _write;
|
|
||||||
translation = _translation;
|
translation = _translation;
|
||||||
|
|
||||||
VAddr addr = vaddr;
|
VAddr addr = vaddr;
|
||||||
|
@ -451,14 +450,14 @@ Walker::recvTiming(PacketPtr pkt)
|
||||||
* well.
|
* well.
|
||||||
*/
|
*/
|
||||||
bool delayedResponse;
|
bool delayedResponse;
|
||||||
Fault fault = tlb->translate(req, tc, NULL, write, execute,
|
Fault fault = tlb->translate(req, tc, NULL, mode,
|
||||||
delayedResponse, true);
|
delayedResponse, true);
|
||||||
assert(!delayedResponse);
|
assert(!delayedResponse);
|
||||||
// Let the CPU continue.
|
// Let the CPU continue.
|
||||||
translation->finish(fault, req, tc, write);
|
translation->finish(fault, req, tc, mode);
|
||||||
} else {
|
} else {
|
||||||
// There was a fault during the walk. Let the CPU know.
|
// There was a fault during the walk. Let the CPU know.
|
||||||
translation->finish(timingFault, req, tc, write);
|
translation->finish(timingFault, req, tc, mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (pkt->wasNacked()) {
|
} else if (pkt->wasNacked()) {
|
||||||
|
@ -563,8 +562,9 @@ Walker::pageFault(bool present)
|
||||||
{
|
{
|
||||||
DPRINTF(PageTableWalker, "Raising page fault.\n");
|
DPRINTF(PageTableWalker, "Raising page fault.\n");
|
||||||
HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
|
HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
|
||||||
return new PageFault(entry.vaddr, present, write,
|
if (mode == BaseTLB::Execute && !enableNX)
|
||||||
m5reg.cpl == 3, false, execute && enableNX);
|
mode = BaseTLB::Read;
|
||||||
|
return new PageFault(entry.vaddr, present, mode, m5reg.cpl == 3, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ namespace X86ISA
|
||||||
|
|
||||||
// Kick off the state machine.
|
// Kick off the state machine.
|
||||||
Fault start(ThreadContext * _tc, BaseTLB::Translation *translation,
|
Fault start(ThreadContext * _tc, BaseTLB::Translation *translation,
|
||||||
RequestPtr req, bool write, bool execute);
|
RequestPtr req, BaseTLB::Mode mode);
|
||||||
// Clean up after the state machine.
|
// Clean up after the state machine.
|
||||||
void
|
void
|
||||||
stop()
|
stop()
|
||||||
|
@ -183,7 +183,8 @@ namespace X86ISA
|
||||||
State nextState;
|
State nextState;
|
||||||
int size;
|
int size;
|
||||||
bool enableNX;
|
bool enableNX;
|
||||||
bool write, execute, user;
|
BaseTLB::Mode mode;
|
||||||
|
bool user;
|
||||||
TlbEntry entry;
|
TlbEntry entry;
|
||||||
|
|
||||||
Fault pageFault(bool present);
|
Fault pageFault(bool present);
|
||||||
|
|
|
@ -186,9 +186,8 @@ TLB::demapPage(Addr va, uint64_t asn)
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault
|
Fault
|
||||||
TLB::translate(RequestPtr req, ThreadContext *tc,
|
TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation,
|
||||||
Translation *translation, bool write, bool execute,
|
Mode mode, bool &delayedResponse, bool timing)
|
||||||
bool &delayedResponse, bool timing)
|
|
||||||
{
|
{
|
||||||
delayedResponse = false;
|
delayedResponse = false;
|
||||||
Addr vaddr = req->getVaddr();
|
Addr vaddr = req->getVaddr();
|
||||||
|
@ -577,9 +576,9 @@ TLB::translate(RequestPtr req, ThreadContext *tc,
|
||||||
bool expandDown = false;
|
bool expandDown = false;
|
||||||
SegAttr attr = tc->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg));
|
SegAttr attr = tc->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg));
|
||||||
if (seg >= SEGMENT_REG_ES && seg <= SEGMENT_REG_HS) {
|
if (seg >= SEGMENT_REG_ES && seg <= SEGMENT_REG_HS) {
|
||||||
if (!attr.writable && write)
|
if (!attr.writable && mode == Write)
|
||||||
return new GeneralProtection(0);
|
return new GeneralProtection(0);
|
||||||
if (!attr.readable && !write && !execute)
|
if (!attr.readable && mode == Read)
|
||||||
return new GeneralProtection(0);
|
return new GeneralProtection(0);
|
||||||
expandDown = attr.expandDown;
|
expandDown = attr.expandDown;
|
||||||
|
|
||||||
|
@ -612,8 +611,7 @@ TLB::translate(RequestPtr req, ThreadContext *tc,
|
||||||
TlbEntry *entry = lookup(vaddr);
|
TlbEntry *entry = lookup(vaddr);
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
Fault fault = walker->start(tc, translation, req,
|
Fault fault = walker->start(tc, translation, req, mode);
|
||||||
write, execute);
|
|
||||||
if (timing || fault != NoFault) {
|
if (timing || fault != NoFault) {
|
||||||
// This gets ignored in atomic mode.
|
// This gets ignored in atomic mode.
|
||||||
delayedResponse = true;
|
delayedResponse = true;
|
||||||
|
@ -629,7 +627,7 @@ TLB::translate(RequestPtr req, ThreadContext *tc,
|
||||||
Process *p = tc->getProcessPtr();
|
Process *p = tc->getProcessPtr();
|
||||||
TlbEntry newEntry;
|
TlbEntry newEntry;
|
||||||
bool success = p->pTable->lookup(vaddr, newEntry);
|
bool success = p->pTable->lookup(vaddr, newEntry);
|
||||||
if(!success && !execute) {
|
if(!success && mode != Execute) {
|
||||||
p->checkAndAllocNextPage(vaddr);
|
p->checkAndAllocNextPage(vaddr);
|
||||||
success = p->pTable->lookup(vaddr, newEntry);
|
success = p->pTable->lookup(vaddr, newEntry);
|
||||||
}
|
}
|
||||||
|
@ -648,12 +646,11 @@ TLB::translate(RequestPtr req, ThreadContext *tc,
|
||||||
bool inUser = (csAttr.dpl == 3 &&
|
bool inUser = (csAttr.dpl == 3 &&
|
||||||
!(flags & (CPL0FlagBit << FlagShift)));
|
!(flags & (CPL0FlagBit << FlagShift)));
|
||||||
if ((inUser && !entry->user) ||
|
if ((inUser && !entry->user) ||
|
||||||
(write && !entry->writable)) {
|
(mode == Write && !entry->writable)) {
|
||||||
// The page must have been present to get into the TLB in
|
// The page must have been present to get into the TLB in
|
||||||
// the first place. We'll assume the reserved bits are
|
// the first place. We'll assume the reserved bits are
|
||||||
// fine even though we're not checking them.
|
// fine even though we're not checking them.
|
||||||
return new PageFault(vaddr, true, write,
|
return new PageFault(vaddr, true, mode, inUser, false);
|
||||||
inUser, false, execute);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -700,24 +697,22 @@ TLB::translate(RequestPtr req, ThreadContext *tc,
|
||||||
};
|
};
|
||||||
|
|
||||||
Fault
|
Fault
|
||||||
TLB::translateAtomic(RequestPtr req, ThreadContext *tc,
|
TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode)
|
||||||
bool write, bool execute)
|
|
||||||
{
|
{
|
||||||
bool delayedResponse;
|
bool delayedResponse;
|
||||||
return TLB::translate(req, tc, NULL, write,
|
return TLB::translate(req, tc, NULL, mode, delayedResponse, false);
|
||||||
execute, delayedResponse, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TLB::translateTiming(RequestPtr req, ThreadContext *tc,
|
TLB::translateTiming(RequestPtr req, ThreadContext *tc,
|
||||||
Translation *translation, bool write, bool execute)
|
Translation *translation, Mode mode)
|
||||||
{
|
{
|
||||||
bool delayedResponse;
|
bool delayedResponse;
|
||||||
assert(translation);
|
assert(translation);
|
||||||
Fault fault = TLB::translate(req, tc, translation,
|
Fault fault =
|
||||||
write, execute, delayedResponse, true);
|
TLB::translate(req, tc, translation, mode, delayedResponse, true);
|
||||||
if (!delayedResponse)
|
if (!delayedResponse)
|
||||||
translation->finish(fault, req, tc, write, execute);
|
translation->finish(fault, req, tc, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
|
|
|
@ -127,16 +127,14 @@ namespace X86ISA
|
||||||
EntryList entryList;
|
EntryList entryList;
|
||||||
|
|
||||||
Fault translate(RequestPtr req, ThreadContext *tc,
|
Fault translate(RequestPtr req, ThreadContext *tc,
|
||||||
Translation *translation, bool write, bool execute,
|
Translation *translation, Mode mode,
|
||||||
bool &delayedResponse, bool timing);
|
bool &delayedResponse, bool timing);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Fault translateAtomic(RequestPtr req, ThreadContext *tc,
|
Fault translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode);
|
||||||
bool write = false, bool execute = false);
|
|
||||||
void translateTiming(RequestPtr req, ThreadContext *tc,
|
void translateTiming(RequestPtr req, ThreadContext *tc,
|
||||||
Translation *translation,
|
Translation *translation, Mode mode);
|
||||||
bool write = false, bool execute = false);
|
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
Tick doMmuRegRead(ThreadContext *tc, Packet *pkt);
|
Tick doMmuRegRead(ThreadContext *tc, Packet *pkt);
|
||||||
|
|
|
@ -38,7 +38,7 @@ import sys
|
||||||
default_tracer = ExeTracer()
|
default_tracer = ExeTracer()
|
||||||
|
|
||||||
if build_env['TARGET_ISA'] == 'alpha':
|
if build_env['TARGET_ISA'] == 'alpha':
|
||||||
from AlphaTLB import AlphaTLB
|
from AlphaTLB import AlphaDTB, AlphaITB
|
||||||
if build_env['FULL_SYSTEM']:
|
if build_env['FULL_SYSTEM']:
|
||||||
from AlphaInterrupts import AlphaInterrupts
|
from AlphaInterrupts import AlphaInterrupts
|
||||||
elif build_env['TARGET_ISA'] == 'sparc':
|
elif build_env['TARGET_ISA'] == 'sparc':
|
||||||
|
@ -54,7 +54,7 @@ elif build_env['TARGET_ISA'] == 'mips':
|
||||||
if build_env['FULL_SYSTEM']:
|
if build_env['FULL_SYSTEM']:
|
||||||
from MipsInterrupts import MipsInterrupts
|
from MipsInterrupts import MipsInterrupts
|
||||||
elif build_env['TARGET_ISA'] == 'arm':
|
elif build_env['TARGET_ISA'] == 'arm':
|
||||||
from ArmTLB import ArmTLB, ArmDTB, ArmITB, ArmUTB
|
from ArmTLB import ArmDTB
|
||||||
if build_env['FULL_SYSTEM']:
|
if build_env['FULL_SYSTEM']:
|
||||||
from ArmInterrupts import ArmInterrupts
|
from ArmInterrupts import ArmInterrupts
|
||||||
|
|
||||||
|
@ -89,8 +89,8 @@ class BaseCPU(MemObject):
|
||||||
interrupts = Param.SparcInterrupts(
|
interrupts = Param.SparcInterrupts(
|
||||||
SparcInterrupts(), "Interrupt Controller")
|
SparcInterrupts(), "Interrupt Controller")
|
||||||
elif build_env['TARGET_ISA'] == 'alpha':
|
elif build_env['TARGET_ISA'] == 'alpha':
|
||||||
dtb = Param.AlphaTLB(AlphaTLB(size=64), "Data TLB")
|
dtb = Param.AlphaTLB(AlphaDTB(), "Data TLB")
|
||||||
itb = Param.AlphaTLB(AlphaTLB(size=48), "Instruction TLB")
|
itb = Param.AlphaTLB(AlphaITB(), "Instruction TLB")
|
||||||
if build_env['FULL_SYSTEM']:
|
if build_env['FULL_SYSTEM']:
|
||||||
interrupts = Param.AlphaInterrupts(
|
interrupts = Param.AlphaInterrupts(
|
||||||
AlphaInterrupts(), "Interrupt Controller")
|
AlphaInterrupts(), "Interrupt Controller")
|
||||||
|
@ -109,9 +109,8 @@ class BaseCPU(MemObject):
|
||||||
MipsInterrupts(), "Interrupt Controller")
|
MipsInterrupts(), "Interrupt Controller")
|
||||||
elif build_env['TARGET_ISA'] == 'arm':
|
elif build_env['TARGET_ISA'] == 'arm':
|
||||||
UnifiedTLB = Param.Bool(True, "Is this a Unified TLB?")
|
UnifiedTLB = Param.Bool(True, "Is this a Unified TLB?")
|
||||||
dtb = Param.ArmDTB(ArmDTB(), "Data TLB")
|
dtb = Param.ArmTLB(ArmDTB(), "Data TLB")
|
||||||
itb = Param.ArmITB(ArmITB(), "Instruction TLB")
|
itb = Param.ArmTLB(ArmITB(), "Instruction TLB")
|
||||||
tlb = Param.ArmUTB(ArmUTB(), "Unified TLB")
|
|
||||||
if build_env['FULL_SYSTEM']:
|
if build_env['FULL_SYSTEM']:
|
||||||
interrupts = Param.ArmInterrupts(
|
interrupts = Param.ArmInterrupts(
|
||||||
ArmInterrupts(), "Interrupt Controller")
|
ArmInterrupts(), "Interrupt Controller")
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include "cpu/static_inst.hh"
|
#include "cpu/static_inst.hh"
|
||||||
#include "mem/packet.hh"
|
#include "mem/packet.hh"
|
||||||
#include "sim/system.hh"
|
#include "sim/system.hh"
|
||||||
|
#include "sim/tlb.hh"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
|
@ -860,7 +861,7 @@ BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
|
||||||
req->setVirt(asid, addr, sizeof(T), flags, this->PC);
|
req->setVirt(asid, addr, sizeof(T), flags, this->PC);
|
||||||
req->setThreadContext(thread->contextId(), threadNumber);
|
req->setThreadContext(thread->contextId(), threadNumber);
|
||||||
|
|
||||||
fault = cpu->dtb->translateAtomic(req, thread->getTC(), false);
|
fault = cpu->dtb->translateAtomic(req, thread->getTC(), BaseTLB::Read);
|
||||||
|
|
||||||
if (req->isUncacheable())
|
if (req->isUncacheable())
|
||||||
isUncacheable = true;
|
isUncacheable = true;
|
||||||
|
@ -916,7 +917,7 @@ BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
req->setVirt(asid, addr, sizeof(T), flags, this->PC);
|
req->setVirt(asid, addr, sizeof(T), flags, this->PC);
|
||||||
req->setThreadContext(thread->contextId(), threadNumber);
|
req->setThreadContext(thread->contextId(), threadNumber);
|
||||||
|
|
||||||
fault = cpu->dtb->translateAtomic(req, thread->getTC(), true);
|
fault = cpu->dtb->translateAtomic(req, thread->getTC(), BaseTLB::Write);
|
||||||
|
|
||||||
if (req->isUncacheable())
|
if (req->isUncacheable())
|
||||||
isUncacheable = true;
|
isUncacheable = true;
|
||||||
|
|
|
@ -602,7 +602,7 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
|
||||||
|
|
||||||
// Translate the instruction request.
|
// Translate the instruction request.
|
||||||
fault = cpu->itb->translateAtomic(mem_req, cpu->thread[tid]->getTC(),
|
fault = cpu->itb->translateAtomic(mem_req, cpu->thread[tid]->getTC(),
|
||||||
false, true);
|
BaseTLB::Execute);
|
||||||
|
|
||||||
// In the case of faults, the fetch stage may need to stall and wait
|
// In the case of faults, the fetch stage may need to stall and wait
|
||||||
// for the ITB miss to be handled.
|
// for the ITB miss to be handled.
|
||||||
|
|
|
@ -314,7 +314,7 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
|
||||||
req->setVirt(0, addr, dataSize, flags, thread->readPC());
|
req->setVirt(0, addr, dataSize, flags, thread->readPC());
|
||||||
|
|
||||||
// translate to physical address
|
// translate to physical address
|
||||||
Fault fault = thread->dtb->translateAtomic(req, tc, false);
|
Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Read);
|
||||||
|
|
||||||
// Now do the access.
|
// Now do the access.
|
||||||
if (fault == NoFault) {
|
if (fault == NoFault) {
|
||||||
|
@ -452,7 +452,7 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
req->setVirt(0, addr, dataSize, flags, thread->readPC());
|
req->setVirt(0, addr, dataSize, flags, thread->readPC());
|
||||||
|
|
||||||
// translate to physical address
|
// translate to physical address
|
||||||
Fault fault = thread->dtb->translateAtomic(req, tc, true);
|
Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Write);
|
||||||
|
|
||||||
// Now do the access.
|
// Now do the access.
|
||||||
if (fault == NoFault) {
|
if (fault == NoFault) {
|
||||||
|
@ -609,7 +609,8 @@ AtomicSimpleCPU::tick()
|
||||||
bool fromRom = isRomMicroPC(thread->readMicroPC());
|
bool fromRom = isRomMicroPC(thread->readMicroPC());
|
||||||
if (!fromRom && !curMacroStaticInst) {
|
if (!fromRom && !curMacroStaticInst) {
|
||||||
setupFetchRequest(&ifetch_req);
|
setupFetchRequest(&ifetch_req);
|
||||||
fault = thread->itb->translateAtomic(&ifetch_req, tc, false, true);
|
fault = thread->itb->translateAtomic(&ifetch_req, tc,
|
||||||
|
BaseTLB::Execute);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fault == NoFault) {
|
if (fault == NoFault) {
|
||||||
|
|
|
@ -454,15 +454,15 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags)
|
||||||
|
|
||||||
typedef SplitDataTranslation::WholeTranslationState WholeState;
|
typedef SplitDataTranslation::WholeTranslationState WholeState;
|
||||||
WholeState *state = new WholeState(req1, req2, req,
|
WholeState *state = new WholeState(req1, req2, req,
|
||||||
(uint8_t *)(new T), true);
|
(uint8_t *)(new T), BaseTLB::Read);
|
||||||
thread->dtb->translateTiming(req1, tc,
|
thread->dtb->translateTiming(req1, tc,
|
||||||
new SplitDataTranslation(this, 0, state), false);
|
new SplitDataTranslation(this, 0, state), BaseTLB::Read);
|
||||||
thread->dtb->translateTiming(req2, tc,
|
thread->dtb->translateTiming(req2, tc,
|
||||||
new SplitDataTranslation(this, 1, state), false);
|
new SplitDataTranslation(this, 1, state), BaseTLB::Read);
|
||||||
} else {
|
} else {
|
||||||
thread->dtb->translateTiming(req, tc,
|
DataTranslation *translation =
|
||||||
new DataTranslation(this, (uint8_t *)(new T), NULL, true),
|
new DataTranslation(this, (uint8_t *)(new T), NULL, BaseTLB::Read);
|
||||||
false);
|
thread->dtb->translateTiming(req, tc, translation, BaseTLB::Read);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (traceData) {
|
if (traceData) {
|
||||||
|
@ -573,15 +573,15 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
|
|
||||||
typedef SplitDataTranslation::WholeTranslationState WholeState;
|
typedef SplitDataTranslation::WholeTranslationState WholeState;
|
||||||
WholeState *state = new WholeState(req1, req2, req,
|
WholeState *state = new WholeState(req1, req2, req,
|
||||||
(uint8_t *)dataP, false);
|
(uint8_t *)dataP, BaseTLB::Write);
|
||||||
thread->dtb->translateTiming(req1, tc,
|
thread->dtb->translateTiming(req1, tc,
|
||||||
new SplitDataTranslation(this, 0, state), true);
|
new SplitDataTranslation(this, 0, state), BaseTLB::Write);
|
||||||
thread->dtb->translateTiming(req2, tc,
|
thread->dtb->translateTiming(req2, tc,
|
||||||
new SplitDataTranslation(this, 1, state), true);
|
new SplitDataTranslation(this, 1, state), BaseTLB::Write);
|
||||||
} else {
|
} else {
|
||||||
thread->dtb->translateTiming(req, tc,
|
DataTranslation *translation =
|
||||||
new DataTranslation(this, (uint8_t *)dataP, res, false),
|
new DataTranslation(this, (uint8_t *)dataP, res, BaseTLB::Write);
|
||||||
true);
|
thread->dtb->translateTiming(req, tc, translation, BaseTLB::Write);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (traceData) {
|
if (traceData) {
|
||||||
|
@ -671,8 +671,8 @@ TimingSimpleCPU::fetch()
|
||||||
Request *ifetch_req = new Request();
|
Request *ifetch_req = new Request();
|
||||||
ifetch_req->setThreadContext(_cpuId, /* thread ID */ 0);
|
ifetch_req->setThreadContext(_cpuId, /* thread ID */ 0);
|
||||||
setupFetchRequest(ifetch_req);
|
setupFetchRequest(ifetch_req);
|
||||||
thread->itb->translateTiming(ifetch_req, tc,
|
thread->itb->translateTiming(ifetch_req, tc, &fetchTranslation,
|
||||||
&fetchTranslation, false, true);
|
BaseTLB::Execute);
|
||||||
} else {
|
} else {
|
||||||
_status = IcacheWaitResponse;
|
_status = IcacheWaitResponse;
|
||||||
completeIfetch(NULL);
|
completeIfetch(NULL);
|
||||||
|
|
|
@ -102,11 +102,13 @@ class TimingSimpleCPU : public BaseSimpleCPU
|
||||||
TimingSimpleCPU *cpu;
|
TimingSimpleCPU *cpu;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FetchTranslation(TimingSimpleCPU *_cpu) : cpu(_cpu)
|
FetchTranslation(TimingSimpleCPU *_cpu)
|
||||||
|
: cpu(_cpu)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void finish(Fault fault, RequestPtr req,
|
void
|
||||||
ThreadContext *tc, bool write, bool execute)
|
finish(Fault fault, RequestPtr req, ThreadContext *tc,
|
||||||
|
BaseTLB::Mode mode)
|
||||||
{
|
{
|
||||||
cpu->sendFetch(fault, req, tc);
|
cpu->sendFetch(fault, req, tc);
|
||||||
}
|
}
|
||||||
|
@ -119,19 +121,22 @@ class TimingSimpleCPU : public BaseSimpleCPU
|
||||||
TimingSimpleCPU *cpu;
|
TimingSimpleCPU *cpu;
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
uint64_t *res;
|
uint64_t *res;
|
||||||
bool read;
|
BaseTLB::Mode mode;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DataTranslation(TimingSimpleCPU *_cpu,
|
DataTranslation(TimingSimpleCPU *_cpu,
|
||||||
uint8_t *_data, uint64_t *_res, bool _read) :
|
uint8_t *_data, uint64_t *_res, BaseTLB::Mode _mode)
|
||||||
cpu(_cpu), data(_data), res(_res), read(_read)
|
: cpu(_cpu), data(_data), res(_res), mode(_mode)
|
||||||
{}
|
{
|
||||||
|
assert(mode == BaseTLB::Read || mode == BaseTLB::Write);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
finish(Fault fault, RequestPtr req,
|
finish(Fault fault, RequestPtr req, ThreadContext *tc,
|
||||||
ThreadContext *tc, bool write, bool execute)
|
BaseTLB::Mode mode)
|
||||||
{
|
{
|
||||||
cpu->sendData(fault, req, data, res, read);
|
assert(mode == this->mode);
|
||||||
|
cpu->sendData(fault, req, data, res, mode == BaseTLB::Read);
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -147,18 +152,20 @@ class TimingSimpleCPU : public BaseSimpleCPU
|
||||||
RequestPtr mainReq;
|
RequestPtr mainReq;
|
||||||
Fault faults[2];
|
Fault faults[2];
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
bool read;
|
BaseTLB::Mode mode;
|
||||||
|
|
||||||
WholeTranslationState(RequestPtr req1, RequestPtr req2,
|
WholeTranslationState(RequestPtr req1, RequestPtr req2,
|
||||||
RequestPtr main, uint8_t *_data, bool _read)
|
RequestPtr main, uint8_t *data, BaseTLB::Mode mode)
|
||||||
{
|
{
|
||||||
|
assert(mode == BaseTLB::Read || mode == BaseTLB::Write);
|
||||||
|
|
||||||
outstanding = 2;
|
outstanding = 2;
|
||||||
requests[0] = req1;
|
requests[0] = req1;
|
||||||
requests[1] = req2;
|
requests[1] = req2;
|
||||||
mainReq = main;
|
mainReq = main;
|
||||||
faults[0] = faults[1] = NoFault;
|
faults[0] = faults[1] = NoFault;
|
||||||
data = _data;
|
this->data = data;
|
||||||
read = _read;
|
this->mode = mode;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -167,13 +174,13 @@ class TimingSimpleCPU : public BaseSimpleCPU
|
||||||
WholeTranslationState *state;
|
WholeTranslationState *state;
|
||||||
|
|
||||||
SplitDataTranslation(TimingSimpleCPU *_cpu, int _index,
|
SplitDataTranslation(TimingSimpleCPU *_cpu, int _index,
|
||||||
WholeTranslationState *_state) :
|
WholeTranslationState *_state)
|
||||||
cpu(_cpu), index(_index), state(_state)
|
: cpu(_cpu), index(_index), state(_state)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void
|
void
|
||||||
finish(Fault fault, RequestPtr req,
|
finish(Fault fault, RequestPtr req, ThreadContext *tc,
|
||||||
ThreadContext *tc, bool write, bool execute)
|
BaseTLB::Mode mode)
|
||||||
{
|
{
|
||||||
assert(state);
|
assert(state);
|
||||||
assert(state->outstanding);
|
assert(state->outstanding);
|
||||||
|
@ -185,7 +192,7 @@ class TimingSimpleCPU : public BaseSimpleCPU
|
||||||
state->requests[1],
|
state->requests[1],
|
||||||
state->mainReq,
|
state->mainReq,
|
||||||
state->data,
|
state->data,
|
||||||
state->read);
|
state->mode == BaseTLB::Read);
|
||||||
delete state;
|
delete state;
|
||||||
}
|
}
|
||||||
delete this;
|
delete this;
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
#include "sim/tlb.hh"
|
#include "sim/tlb.hh"
|
||||||
|
|
||||||
Fault
|
Fault
|
||||||
GenericTLB::translateAtomic(RequestPtr req, ThreadContext * tc, bool, bool)
|
GenericTLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode)
|
||||||
{
|
{
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
panic("Generic translation shouldn't be used in full system mode.\n");
|
panic("Generic translation shouldn't be used in full system mode.\n");
|
||||||
|
@ -51,11 +51,10 @@ GenericTLB::translateAtomic(RequestPtr req, ThreadContext * tc, bool, bool)
|
||||||
|
|
||||||
void
|
void
|
||||||
GenericTLB::translateTiming(RequestPtr req, ThreadContext *tc,
|
GenericTLB::translateTiming(RequestPtr req, ThreadContext *tc,
|
||||||
Translation *translation, bool write, bool execute)
|
Translation *translation, Mode mode)
|
||||||
{
|
{
|
||||||
assert(translation);
|
assert(translation);
|
||||||
translation->finish(translateAtomic(req, tc, write, execute),
|
translation->finish(translateAtomic(req, tc, mode), req, tc, mode);
|
||||||
req, tc, write, execute);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -42,9 +42,13 @@ class Packet;
|
||||||
class BaseTLB : public SimObject
|
class BaseTLB : public SimObject
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
BaseTLB(const Params *p) : SimObject(p)
|
BaseTLB(const Params *p)
|
||||||
|
: SimObject(p)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Mode { Read, Write, Execute };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void demapPage(Addr vaddr, uint64_t asn) = 0;
|
virtual void demapPage(Addr vaddr, uint64_t asn) = 0;
|
||||||
|
|
||||||
|
@ -59,24 +63,24 @@ class BaseTLB : public SimObject
|
||||||
* be responsible for cleaning itself up which will happen in this
|
* be responsible for cleaning itself up which will happen in this
|
||||||
* function. Once it's called, the object is no longer valid.
|
* function. Once it's called, the object is no longer valid.
|
||||||
*/
|
*/
|
||||||
virtual void finish(Fault fault, RequestPtr req,
|
virtual void finish(Fault fault, RequestPtr req, ThreadContext *tc,
|
||||||
ThreadContext *tc, bool write=false, bool execute=false) = 0;
|
Mode mode) = 0;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
class GenericTLB : public BaseTLB
|
class GenericTLB : public BaseTLB
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
GenericTLB(const Params *p) : BaseTLB(p)
|
GenericTLB(const Params *p)
|
||||||
|
: BaseTLB(p)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void demapPage(Addr vaddr, uint64_t asn);
|
void demapPage(Addr vaddr, uint64_t asn);
|
||||||
|
|
||||||
Fault translateAtomic(RequestPtr req, ThreadContext *tc,
|
Fault translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode);
|
||||||
bool=false, bool=false);
|
|
||||||
void translateTiming(RequestPtr req, ThreadContext *tc,
|
void translateTiming(RequestPtr req, ThreadContext *tc,
|
||||||
Translation *translation, bool=false, bool=false);
|
Translation *translation, Mode mode);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __ARCH_SPARC_TLB_HH__
|
#endif // __ARCH_SPARC_TLB_HH__
|
||||||
|
|
Loading…
Reference in a new issue