X86: Split out the internal memory space from the regular translate() and precompute mode.

This commit is contained in:
Gabe Black 2009-04-26 16:48:44 -07:00
parent 4ee34dfb4e
commit b6bfe8af26
4 changed files with 382 additions and 373 deletions

View file

@ -118,6 +118,8 @@ void MiscRegFile::updateHandyM5Reg(Efer efer, CR0 cr0,
} }
} }
m5reg.cpl = csAttr.dpl; m5reg.cpl = csAttr.dpl;
m5reg.paging = cr0.pg;
m5reg.prot = cr0.pe;
regVal[MISCREG_M5_REG] = m5reg; regVal[MISCREG_M5_REG] = m5reg;
} }

View file

@ -518,6 +518,8 @@ namespace X86ISA
Bitfield<0> mode; Bitfield<0> mode;
Bitfield<3, 1> submode; Bitfield<3, 1> submode;
Bitfield<5, 4> cpl; Bitfield<5, 4> cpl;
Bitfield<6> paging;
Bitfield<7> prot;
EndBitUnion(HandyM5Reg) EndBitUnion(HandyM5Reg)
/** /**

View file

@ -186,21 +186,10 @@ TLB::demapPage(Addr va, uint64_t asn)
} }
Fault Fault
TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation, TLB::translateInt(RequestPtr req, ThreadContext *tc)
Mode mode, bool &delayedResponse, bool timing)
{ {
delayedResponse = false;
Addr vaddr = req->getVaddr();
DPRINTF(TLB, "Translating vaddr %#x.\n", vaddr);
uint32_t flags = req->getFlags();
bool storeCheck = flags & (StoreCheck << FlagShift);
int seg = flags & SegmentFlagMask;
// If this is true, we're dealing with a request to read an internal
// value.
if (seg == SEGMENT_REG_MS) {
DPRINTF(TLB, "Addresses references internal memory.\n"); DPRINTF(TLB, "Addresses references internal memory.\n");
Addr vaddr = req->getVaddr();
Addr prefix = (vaddr >> 3) & IntAddrPrefixMask; Addr prefix = (vaddr >> 3) & IntAddrPrefixMask;
if (prefix == IntAddrPrefixCPUID) { if (prefix == IntAddrPrefixCPUID) {
panic("CPUID memory space not yet implemented!\n"); panic("CPUID memory space not yet implemented!\n");
@ -553,24 +542,37 @@ TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation,
panic("Access to unrecognized internal address space %#x.\n", panic("Access to unrecognized internal address space %#x.\n",
prefix); prefix);
} }
}
Fault
TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation,
Mode mode, bool &delayedResponse, bool timing)
{
uint32_t flags = req->getFlags();
int seg = flags & SegmentFlagMask;
bool storeCheck = flags & (StoreCheck << FlagShift);
// If this is true, we're dealing with a request to a non-memory address
// space.
if (seg == SEGMENT_REG_MS) {
return translateInt(req, tc);
} }
// Get cr0. This will tell us how to do translation. We'll assume it was delayedResponse = false;
// verified to be correct and consistent when set. Addr vaddr = req->getVaddr();
CR0 cr0 = tc->readMiscRegNoEffect(MISCREG_CR0); DPRINTF(TLB, "Translating vaddr %#x.\n", vaddr);
HandyM5Reg m5Reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
// If protected mode has been enabled... // If protected mode has been enabled...
if (cr0.pe) { if (m5Reg.prot) {
DPRINTF(TLB, "In protected mode.\n"); DPRINTF(TLB, "In protected mode.\n");
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 we're not in 64-bit mode, do protection/limit checks
if (!efer.lma || !csAttr.longMode) { if (m5Reg.mode != LongMode) {
DPRINTF(TLB, "Not in long mode. Checking segment protection.\n"); DPRINTF(TLB, "Not in long mode. Checking segment protection.\n");
// Check for a NULL segment selector. // Check for a NULL segment selector.
if (!(seg == SEGMENT_REG_TSG || seg == SYS_SEGMENT_REG_IDTR || if (!(seg == SEGMENT_REG_TSG || seg == SYS_SEGMENT_REG_IDTR ||
seg == SEGMENT_REG_HS || seg == SEGMENT_REG_LS || seg == SEGMENT_REG_HS || seg == SEGMENT_REG_LS)
seg == SEGMENT_REG_MS)
&& !tc->readMiscRegNoEffect(MISCREG_SEG_SEL(seg))) && !tc->readMiscRegNoEffect(MISCREG_SEG_SEL(seg)))
return new GeneralProtection(0); return new GeneralProtection(0);
bool expandDown = false; bool expandDown = false;
@ -589,6 +591,7 @@ TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation,
// address size is 64 bits, overridable to 32. // address size is 64 bits, overridable to 32.
int size = 32; int size = 32;
bool sizeOverride = (flags & (AddrSizeFlagBit << FlagShift)); bool sizeOverride = (flags & (AddrSizeFlagBit << FlagShift));
SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR);
if ((csAttr.defaultSize && sizeOverride) || if ((csAttr.defaultSize && sizeOverride) ||
(!csAttr.defaultSize && !sizeOverride)) (!csAttr.defaultSize && !sizeOverride))
size = 16; size = 16;
@ -605,7 +608,7 @@ TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation,
} }
} }
// If paging is enabled, do the translation. // If paging is enabled, do the translation.
if (cr0.pg) { if (m5Reg.paging) {
DPRINTF(TLB, "Paging enabled.\n"); DPRINTF(TLB, "Paging enabled.\n");
// The vaddr already has the segment base applied. // The vaddr already has the segment base applied.
TlbEntry *entry = lookup(vaddr); TlbEntry *entry = lookup(vaddr);
@ -643,7 +646,7 @@ TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation,
#endif #endif
} }
// Do paging protection checks. // Do paging protection checks.
bool inUser = (csAttr.dpl == 3 && bool inUser = (m5Reg.cpl == 3 &&
!(flags & (CPL0FlagBit << FlagShift))); !(flags & (CPL0FlagBit << FlagShift)));
if ((inUser && !entry->user) || if ((inUser && !entry->user) ||
(mode == Write && !entry->writable)) { (mode == Write && !entry->writable)) {

View file

@ -124,6 +124,8 @@ namespace X86ISA
EntryList freeList; EntryList freeList;
EntryList entryList; EntryList entryList;
Fault translateInt(RequestPtr req, ThreadContext *tc);
Fault translate(RequestPtr req, ThreadContext *tc, Fault translate(RequestPtr req, ThreadContext *tc,
Translation *translation, Mode mode, Translation *translation, Mode mode,
bool &delayedResponse, bool timing); bool &delayedResponse, bool timing);