x86: Add bitfields which can gather/scatter bases and limits.
Add bitfields which can gather/scatter base and limit fields within "normal" segment descriptors, and in TSS descriptors which have the same bitfields in the same positions for those two values. This centralizes the code which manages those bitfields and makes it less likely that a local implementation will be buggy. Change-Id: I9809aa626fc31388595c3d3b225c25a0ec6a1275 Reviewed-on: https://gem5-review.googlesource.com/7661 Reviewed-by: Gabe Black <gabeblack@google.com> Maintainer: Gabe Black <gabeblack@google.com>
This commit is contained in:
@@ -1627,8 +1627,7 @@ let {{
|
||||
case LDT64:
|
||||
case AvailableTSS64:
|
||||
case BusyTSS64:
|
||||
replaceBits(target, 23, 0, desc.baseLow);
|
||||
replaceBits(target, 31, 24, desc.baseHigh);
|
||||
replaceBits(target, 31, 0, desc.base);
|
||||
break;
|
||||
case CallGate64:
|
||||
case IntGate64:
|
||||
@@ -1703,12 +1702,8 @@ let {{
|
||||
attr.writable = desc.type.w;
|
||||
}
|
||||
}
|
||||
Addr base = desc.baseLow | (desc.baseHigh << 24);
|
||||
Addr limit = desc.limitLow | (desc.limitHigh << 16);
|
||||
if (desc.g)
|
||||
limit = (limit << 12) | mask(12);
|
||||
SegBaseDest = base;
|
||||
SegLimitDest = limit;
|
||||
SegBaseDest = desc.base;
|
||||
SegLimitDest = desc.limit;
|
||||
SegAttrDest = attr;
|
||||
} else {
|
||||
SegBaseDest = SegBaseDest;
|
||||
|
||||
@@ -244,12 +244,9 @@ X86_64Process::initState()
|
||||
initDesc.p = 1; // present
|
||||
initDesc.l = 1; // longmode - 64 bit
|
||||
initDesc.d = 0; // operand size
|
||||
initDesc.g = 1; // granularity
|
||||
initDesc.s = 1; // system segment
|
||||
initDesc.limitHigh = 0xFFFF;
|
||||
initDesc.limitLow = 0xF;
|
||||
initDesc.baseHigh = 0x0;
|
||||
initDesc.baseLow = 0x0;
|
||||
initDesc.limit = 0xFFFFFFFF;
|
||||
initDesc.base = 0;
|
||||
|
||||
//64 bit code segment
|
||||
SegDescriptor csLowPLDesc = initDesc;
|
||||
@@ -320,11 +317,8 @@ X86_64Process::initState()
|
||||
TSSDescLow.type = 0xB;
|
||||
TSSDescLow.dpl = 0; // Privelege level 0
|
||||
TSSDescLow.p = 1; // Present
|
||||
TSSDescLow.g = 1; // Page granularity
|
||||
TSSDescLow.limitHigh = 0xF;
|
||||
TSSDescLow.limitLow = 0xFFFF;
|
||||
TSSDescLow.baseLow = bits(TSSVirtAddr, 23, 0);
|
||||
TSSDescLow.baseHigh = bits(TSSVirtAddr, 31, 24);
|
||||
TSSDescLow.limit = 0xFFFFFFFF;
|
||||
TSSDescLow.base = bits(TSSVirtAddr, 31, 0);
|
||||
|
||||
TSShigh TSSDescHigh = 0;
|
||||
TSSDescHigh.base = bits(TSSVirtAddr, 63, 32);
|
||||
@@ -342,10 +336,8 @@ X86_64Process::initState()
|
||||
SegSelector tssSel = 0;
|
||||
tssSel.si = numGDTEntries - 1;
|
||||
|
||||
uint64_t tss_base_addr = (TSSDescHigh.base << 32) |
|
||||
(TSSDescLow.baseHigh << 24) |
|
||||
TSSDescLow.baseLow;
|
||||
uint64_t tss_limit = TSSDescLow.limitLow | (TSSDescLow.limitHigh << 16);
|
||||
uint64_t tss_base_addr = (TSSDescHigh.base << 32) | TSSDescLow.base;
|
||||
uint64_t tss_limit = TSSDescLow.limit;
|
||||
|
||||
SegAttr tss_attr = 0;
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "arch/x86/regs/segment.hh"
|
||||
#include "arch/x86/x86_traits.hh"
|
||||
#include "base/bitunion.hh"
|
||||
#include "base/logging.hh"
|
||||
|
||||
//These get defined in some system headers (at least termbits.h). That confuses
|
||||
//things here significantly.
|
||||
@@ -867,9 +868,54 @@ namespace X86ISA
|
||||
* Segment Descriptors
|
||||
*/
|
||||
|
||||
class SegDescriptorBase
|
||||
{
|
||||
public:
|
||||
uint32_t
|
||||
getter(const uint64_t &storage) const
|
||||
{
|
||||
return (bits(storage, 63, 56) << 24) | bits(storage, 39, 16);
|
||||
}
|
||||
|
||||
void
|
||||
setter(uint64_t &storage, uint32_t base)
|
||||
{
|
||||
replaceBits(storage, 63, 56, bits(base, 31, 24));
|
||||
replaceBits(storage, 39, 16, bits(base, 23, 0));
|
||||
}
|
||||
};
|
||||
|
||||
class SegDescriptorLimit
|
||||
{
|
||||
public:
|
||||
uint32_t
|
||||
getter(const uint64_t &storage) const
|
||||
{
|
||||
uint32_t limit = (bits(storage, 51, 48) << 16) |
|
||||
bits(storage, 15, 0);
|
||||
if (bits(storage, 55))
|
||||
limit = (limit << 12) | mask(12);
|
||||
return limit;
|
||||
}
|
||||
|
||||
void
|
||||
setter(uint64_t &storage, uint32_t limit)
|
||||
{
|
||||
bool g = (bits(limit, 31, 24) != 0);
|
||||
panic_if(g && bits(limit, 11, 0) != mask(12),
|
||||
"Inlimitid segment limit %#x", limit);
|
||||
if (g)
|
||||
limit = limit >> 12;
|
||||
replaceBits(storage, 51, 48, bits(limit, 23, 16));
|
||||
replaceBits(storage, 15, 0, bits(limit, 15, 0));
|
||||
replaceBits(storage, 55, g ? 1 : 0);
|
||||
}
|
||||
};
|
||||
|
||||
BitUnion64(SegDescriptor)
|
||||
Bitfield<63, 56> baseHigh;
|
||||
Bitfield<39, 16> baseLow;
|
||||
BitfieldType<SegDescriptorBase> base;
|
||||
Bitfield<55> g; // Granularity
|
||||
Bitfield<54> d; // Default Operand Size
|
||||
Bitfield<54> b; // Default Operand Size
|
||||
@@ -877,6 +923,7 @@ namespace X86ISA
|
||||
Bitfield<52> avl; // Available To Software
|
||||
Bitfield<51, 48> limitHigh;
|
||||
Bitfield<15, 0> limitLow;
|
||||
BitfieldType<SegDescriptorLimit> limit;
|
||||
Bitfield<47> p; // Present
|
||||
Bitfield<46, 45> dpl; // Descriptor Privilege-Level
|
||||
Bitfield<44> s; // System
|
||||
@@ -904,10 +951,12 @@ namespace X86ISA
|
||||
BitUnion64(TSSlow)
|
||||
Bitfield<63, 56> baseHigh;
|
||||
Bitfield<39, 16> baseLow;
|
||||
BitfieldType<SegDescriptorBase> base;
|
||||
Bitfield<55> g; // Granularity
|
||||
Bitfield<52> avl; // Available To Software
|
||||
Bitfield<51, 48> limitHigh;
|
||||
Bitfield<15, 0> limitLow;
|
||||
BitfieldType<SegDescriptorLimit> limit;
|
||||
Bitfield<47> p; // Present
|
||||
Bitfield<46, 45> dpl; // Descriptor Privilege-Level
|
||||
SubBitUnion(type, 43, 40)
|
||||
|
||||
@@ -63,14 +63,10 @@ void
|
||||
X86ISA::installSegDesc(ThreadContext *tc, SegmentRegIndex seg,
|
||||
SegDescriptor desc, bool longmode)
|
||||
{
|
||||
uint64_t base = desc.baseLow + (desc.baseHigh << 24);
|
||||
bool honorBase = !longmode || seg == SEGMENT_REG_FS ||
|
||||
seg == SEGMENT_REG_GS ||
|
||||
seg == SEGMENT_REG_TSL ||
|
||||
seg == SYS_SEGMENT_REG_TR;
|
||||
uint64_t limit = desc.limitLow | (desc.limitHigh << 16);
|
||||
if (desc.g)
|
||||
limit = (limit << 12) | mask(12);
|
||||
|
||||
SegAttr attr = 0;
|
||||
|
||||
@@ -101,9 +97,9 @@ X86ISA::installSegDesc(ThreadContext *tc, SegmentRegIndex seg,
|
||||
attr.expandDown = 0;
|
||||
}
|
||||
|
||||
tc->setMiscReg(MISCREG_SEG_BASE(seg), base);
|
||||
tc->setMiscReg(MISCREG_SEG_EFF_BASE(seg), honorBase ? base : 0);
|
||||
tc->setMiscReg(MISCREG_SEG_LIMIT(seg), limit);
|
||||
tc->setMiscReg(MISCREG_SEG_BASE(seg), desc.base);
|
||||
tc->setMiscReg(MISCREG_SEG_EFF_BASE(seg), honorBase ? desc.base : 0);
|
||||
tc->setMiscReg(MISCREG_SEG_LIMIT(seg), desc.limit);
|
||||
tc->setMiscReg(MISCREG_SEG_ATTR(seg), (MiscReg)attr);
|
||||
}
|
||||
|
||||
@@ -159,10 +155,8 @@ X86System::initState()
|
||||
initDesc.d = 0; // operand size
|
||||
initDesc.g = 1; // granularity
|
||||
initDesc.s = 1; // system segment
|
||||
initDesc.limitHigh = 0xF;
|
||||
initDesc.limitLow = 0xFFFF;
|
||||
initDesc.baseHigh = 0x0;
|
||||
initDesc.baseLow = 0x0;
|
||||
initDesc.limit = 0xFFFFFFFF;
|
||||
initDesc.base = 0;
|
||||
|
||||
// 64 bit code segment
|
||||
SegDescriptor csDesc = initDesc;
|
||||
|
||||
Reference in New Issue
Block a user