diff options
-rw-r--r-- | src/arch/x86/isa/microops/regop.isa | 11 | ||||
-rw-r--r-- | src/arch/x86/process.cc | 20 | ||||
-rw-r--r-- | src/arch/x86/regs/misc.hh | 49 | ||||
-rw-r--r-- | src/arch/x86/system.cc | 16 |
4 files changed, 63 insertions, 33 deletions
diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 2d5ae048a..08a4ddd41 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -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; diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index cfec21f39..7c979c016 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -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; diff --git a/src/arch/x86/regs/misc.hh b/src/arch/x86/regs/misc.hh index 48f7d974d..3f3730e32 100644 --- a/src/arch/x86/regs/misc.hh +++ b/src/arch/x86/regs/misc.hh @@ -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) diff --git a/src/arch/x86/system.cc b/src/arch/x86/system.cc index b11111d8d..0f85fdb38 100644 --- a/src/arch/x86/system.cc +++ b/src/arch/x86/system.cc @@ -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; |