X86: Work on the x86 tlb.

--HG--
extra : convert_revision : a08a5cb049a6030ba9fd56a89383d56026238dbf
This commit is contained in:
Gabe Black 2007-10-07 18:18:39 -07:00
parent cd36c69a4d
commit a19c212757
3 changed files with 132 additions and 34 deletions

View file

@ -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

View file

@ -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.
// The vaddr already has the segment base applied.
TlbEntry *entry = lookup(vaddr);
if (!entry) {
// 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 {
Addr paddr = entry->pageStart | (vaddr & mask(12));
req->setPaddr(paddr);
// 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

View file

@ -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);