diff options
author | Gabe Black <gblack@eecs.umich.edu> | 2009-02-27 09:23:50 -0800 |
---|---|---|
committer | Gabe Black <gblack@eecs.umich.edu> | 2009-02-27 09:23:50 -0800 |
commit | 9dfa3f7f735ead0ada9eb79227f217d0d76e0f49 (patch) | |
tree | 5c82e9e2dd91f0b808dd74fdce33863a2c6e128b /src/arch/x86/tlb.cc | |
parent | 9491debaa623aa0ed148ca4bc810f099058b67a1 (diff) | |
download | gem5-9dfa3f7f735ead0ada9eb79227f217d0d76e0f49.tar.xz |
X86: Fix segment limit checks.
Diffstat (limited to 'src/arch/x86/tlb.cc')
-rw-r--r-- | src/arch/x86/tlb.cc | 36 |
1 files changed, 16 insertions, 20 deletions
diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index 603d4e45f..47a2eb37e 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -575,38 +575,34 @@ TLB::translate(RequestPtr req, ThreadContext *tc, if (!tc->readMiscRegNoEffect(MISCREG_SEG_SEL(seg))) return new GeneralProtection(0); bool expandDown = false; + SegAttr attr = tc->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg)); if (seg >= SEGMENT_REG_ES && seg <= SEGMENT_REG_HS) { - 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); expandDown = attr.expandDown; + } Addr base = tc->readMiscRegNoEffect(MISCREG_SEG_BASE(seg)); Addr limit = tc->readMiscRegNoEffect(MISCREG_SEG_LIMIT(seg)); + // This assumes we're not in 64 bit mode. If we were, the default + // address size is 64 bits, overridable to 32. + int size = 32; + bool sizeOverride = (flags & (AddrSizeFlagBit << FlagShift)); + if (csAttr.defaultSize && sizeOverride || + !csAttr.defaultSize && !sizeOverride) + size = 16; + Addr offset = bits(vaddr - base, size-1, 0); + Addr endOffset = offset + req->getSize() - 1; if (expandDown) { DPRINTF(TLB, "Checking an expand down segment.\n"); - // 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); - } + warn_once("Expand down segments are untested.\n"); + if (offset <= limit || endOffset <= limit) + 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 (offset > limit || endOffset > limit) + return new GeneralProtection(0); } } // If paging is enabled, do the translation. |