summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/x86/isa/microops/regop.isa11
-rw-r--r--src/arch/x86/process.cc20
-rw-r--r--src/arch/x86/regs/misc.hh49
-rw-r--r--src/arch/x86/system.cc16
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;