X86: Work on the x86 tlb.
--HG-- extra : convert_revision : a08a5cb049a6030ba9fd56a89383d56026238dbf
This commit is contained in:
parent
cd36c69a4d
commit
a19c212757
3 changed files with 132 additions and 34 deletions
|
@ -147,8 +147,60 @@ void
|
|||
X86LiveProcess::startup()
|
||||
{
|
||||
argsInit(sizeof(IntReg), VMPageSize);
|
||||
for(int i = 0; i < NUM_SEGMENTREGS; i++)
|
||||
threadContexts[0]->setMiscRegNoEffect(MISCREG_ES_BASE + i, 0);
|
||||
|
||||
for (int i = 0; i < threadContexts.size(); i++) {
|
||||
ThreadContext * tc = threadContexts[i];
|
||||
|
||||
SegAttr dataAttr = 0;
|
||||
dataAttr.writable = 1;
|
||||
dataAttr.readable = 1;
|
||||
dataAttr.expandDown = 0;
|
||||
dataAttr.dpl = 3;
|
||||
dataAttr.defaultSize = 0;
|
||||
dataAttr.longMode = 1;
|
||||
|
||||
//Initialize the segment registers.
|
||||
for(int seg = 0; seg < NUM_SEGMENTREGS; seg++) {
|
||||
tc->setMiscRegNoEffect(MISCREG_SEG_BASE(seg), 0);
|
||||
tc->setMiscRegNoEffect(MISCREG_SEG_ATTR(seg), dataAttr);
|
||||
}
|
||||
|
||||
SegAttr csAttr = 0;
|
||||
csAttr.writable = 0;
|
||||
csAttr.readable = 1;
|
||||
csAttr.expandDown = 0;
|
||||
csAttr.dpl = 3;
|
||||
csAttr.defaultSize = 0;
|
||||
csAttr.longMode = 1;
|
||||
|
||||
tc->setMiscRegNoEffect(MISCREG_CS_ATTR, csAttr);
|
||||
|
||||
//Set up the registers that describe the operating mode.
|
||||
CR0 cr0 = 0;
|
||||
cr0.pg = 1; // Turn on paging.
|
||||
cr0.cd = 0; // Don't disable caching.
|
||||
cr0.nw = 0; // This is bit is defined to be ignored.
|
||||
cr0.am = 0; // No alignment checking
|
||||
cr0.wp = 0; // Supervisor mode can write read only pages
|
||||
cr0.ne = 1;
|
||||
cr0.et = 1; // This should always be 1
|
||||
cr0.ts = 0; // We don't do task switching, so causing fp exceptions
|
||||
// would be pointless.
|
||||
cr0.em = 0; // Allow x87 instructions to execute natively.
|
||||
cr0.mp = 1; // This doesn't really matter, but the manual suggests
|
||||
// setting it to one.
|
||||
cr0.pe = 1; // We're definitely in protected mode.
|
||||
tc->setMiscReg(MISCREG_CR0, cr0);
|
||||
|
||||
Efer efer = 0;
|
||||
efer.sce = 1; // Enable system call extensions.
|
||||
efer.lme = 1; // Enable long mode.
|
||||
efer.lma = 1; // Activate long mode.
|
||||
efer.nxe = 1; // Enable nx support.
|
||||
efer.svme = 0; // Disable svm support for now. It isn't implemented.
|
||||
efer.ffxsr = 1; // Turn on fast fxsave and fxrstor.
|
||||
tc->setMiscReg(MISCREG_EFER, efer);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -133,55 +133,98 @@ TLB::demapPage(Addr va)
|
|||
{
|
||||
}
|
||||
|
||||
template<class TlbFault>
|
||||
Fault
|
||||
ITB::translate(RequestPtr &req, ThreadContext *tc)
|
||||
{
|
||||
Addr vaddr = req->getVaddr();
|
||||
// Check against the limit of the CS segment, and permissions.
|
||||
// The vaddr already has the segment base applied.
|
||||
TlbEntry *entry = lookup(vaddr);
|
||||
if (!entry) {
|
||||
#if FULL_SYSTEM
|
||||
return new FakeITLBFault();
|
||||
#else
|
||||
return new FakeITLBFault(vaddr);
|
||||
#endif
|
||||
} else {
|
||||
Addr paddr = entry->pageStart | (vaddr & mask(12));
|
||||
DPRINTF(TLB, "Translated %#x to %#x\n", vaddr, paddr);
|
||||
req->setPaddr(paddr);
|
||||
}
|
||||
|
||||
return NoFault;
|
||||
}
|
||||
|
||||
Fault
|
||||
DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
|
||||
TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute)
|
||||
{
|
||||
Addr vaddr = req->getVaddr();
|
||||
DPRINTF(TLB, "Translating vaddr %#x.\n", vaddr);
|
||||
uint32_t flags = req->getFlags();
|
||||
bool storeCheck = flags & StoreCheck;
|
||||
|
||||
int seg = flags & (mask(NUM_SEGMENTREGS));
|
||||
|
||||
//XXX Junk code to surpress the warning
|
||||
if (storeCheck) seg = seg;
|
||||
|
||||
// Check the limit of the segment "seg", and permissions.
|
||||
// Get cr0. This will tell us how to do translation. We'll assume it was
|
||||
// verified to be correct and consistent when set.
|
||||
CR0 cr0 = tc->readMiscRegNoEffect(MISCREG_CR0);
|
||||
|
||||
// If protected mode has been enabled...
|
||||
if (cr0.pe) {
|
||||
Efer efer = tc->readMiscRegNoEffect(MISCREG_EFER);
|
||||
SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR);
|
||||
// If we're not in 64-bit mode, do protection/limit checks
|
||||
if (!efer.lma || !csAttr.longMode) {
|
||||
SegAttr attr = tc->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg));
|
||||
if (!attr.writable && write)
|
||||
return new GeneralProtection(0);
|
||||
if (!attr.readable && !write && !execute)
|
||||
return new GeneralProtection(0);
|
||||
Addr base = tc->readMiscRegNoEffect(MISCREG_SEG_BASE(seg));
|
||||
Addr limit = tc->readMiscRegNoEffect(MISCREG_SEG_LIMIT(seg));
|
||||
if (!attr.expandDown) {
|
||||
// We don't have to worry about the access going around the
|
||||
// end of memory because accesses will be broken up into
|
||||
// pieces at boundaries aligned on sizes smaller than an
|
||||
// entire address space. We do have to worry about the limit
|
||||
// being less than the base.
|
||||
if (limit < base) {
|
||||
if (limit < vaddr + req->getSize() && vaddr < base)
|
||||
return new GeneralProtection(0);
|
||||
} else {
|
||||
if (limit < vaddr + req->getSize())
|
||||
return new GeneralProtection(0);
|
||||
}
|
||||
} else {
|
||||
if (limit < base) {
|
||||
if (vaddr <= limit || vaddr + req->getSize() >= base)
|
||||
return new GeneralProtection(0);
|
||||
} else {
|
||||
if (vaddr <= limit && vaddr + req->getSize() >= base)
|
||||
return new GeneralProtection(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If paging is enabled, do the translation.
|
||||
if (cr0.pg) {
|
||||
// The vaddr already has the segment base applied.
|
||||
TlbEntry *entry = lookup(vaddr);
|
||||
if (!entry) {
|
||||
#if FULL_SYSTEM
|
||||
return new FakeDTLBFault();
|
||||
return new TlbFault();
|
||||
#else
|
||||
return new FakeDTLBFault(vaddr);
|
||||
return new TlbFault(vaddr);
|
||||
#endif
|
||||
} else {
|
||||
// Do paging protection checks.
|
||||
Addr paddr = entry->pageStart | (vaddr & mask(12));
|
||||
req->setPaddr(paddr);
|
||||
}
|
||||
} else {
|
||||
//Use the address which already has segmentation applied.
|
||||
req->setPaddr(vaddr);
|
||||
}
|
||||
} else {
|
||||
// Real mode
|
||||
req->setPaddr(vaddr);
|
||||
}
|
||||
return NoFault;
|
||||
};
|
||||
|
||||
Fault
|
||||
DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
|
||||
{
|
||||
return TLB::translate<FakeDTLBFault>(req, tc, write, false);
|
||||
}
|
||||
|
||||
Fault
|
||||
ITB::translate(RequestPtr &req, ThreadContext *tc)
|
||||
{
|
||||
return TLB::translate<FakeITLBFault>(req, tc, false, true);
|
||||
}
|
||||
|
||||
#if FULL_SYSTEM
|
||||
|
||||
Tick
|
||||
|
|
|
@ -108,6 +108,10 @@ namespace X86ISA
|
|||
|
||||
void demapPage(Addr va);
|
||||
|
||||
template<class TlbFault>
|
||||
Fault translate(RequestPtr &req, ThreadContext *tc,
|
||||
bool write, bool execute);
|
||||
|
||||
public:
|
||||
// Checkpointing
|
||||
virtual void serialize(std::ostream &os);
|
||||
|
@ -134,7 +138,6 @@ namespace X86ISA
|
|||
DTB(const Params *p) : TLB(p)
|
||||
{
|
||||
}
|
||||
|
||||
Fault translate(RequestPtr &req, ThreadContext *tc, bool write);
|
||||
#if FULL_SYSTEM
|
||||
Tick doMmuRegRead(ThreadContext *tc, Packet *pkt);
|
||||
|
|
Loading…
Reference in a new issue