summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/x86/isa/operands.isa4
-rw-r--r--src/arch/x86/linux/syscalls.cc2
-rw-r--r--src/arch/x86/miscregfile.cc19
-rw-r--r--src/arch/x86/miscregs.hh20
-rw-r--r--src/arch/x86/process.cc1
-rw-r--r--src/arch/x86/utility.cc6
6 files changed, 48 insertions, 4 deletions
diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa
index f50e71727..7a2631a9c 100644
--- a/src/arch/x86/isa/operands.isa
+++ b/src/arch/x86/isa/operands.isa
@@ -121,11 +121,11 @@ def operands {{
# The TOP register should needs to be more protected so that later
# instructions don't map their indexes with an old value.
'TOP': ('ControlReg', 'ub', 'MISCREG_X87_TOP', None, 61),
- 'SegBase': ('ControlReg', 'uqw', 'MISCREG_SEG_BASE(segment)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 70),
+ 'SegBase': ('ControlReg', 'uqw', 'MISCREG_SEG_EFF_BASE(segment)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 70),
'ControlDest': ('ControlReg', 'uqw', 'MISCREG_CR(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 71),
'ControlSrc1': ('ControlReg', 'uqw', 'MISCREG_CR(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 72),
'EferOp': ('ControlReg', 'uqw', 'MISCREG_EFER', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 73),
'CR4Op': ('ControlReg', 'uqw', 'MISCREG_CR4', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 74),
- 'CSBase': ('ControlReg', 'udw', 'MISCREG_CS_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 80),
+ 'CSBase': ('ControlReg', 'udw', 'MISCREG_CS_EFF_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 80),
'Mem': ('Mem', 'uqw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 100)
}};
diff --git a/src/arch/x86/linux/syscalls.cc b/src/arch/x86/linux/syscalls.cc
index c6b2fbb66..ae2ac243b 100644
--- a/src/arch/x86/linux/syscalls.cc
+++ b/src/arch/x86/linux/syscalls.cc
@@ -103,6 +103,7 @@ archPrctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
//Each of these valid options should actually check addr.
case SetFS:
tc->setMiscRegNoEffect(MISCREG_FS_BASE, addr);
+ tc->setMiscRegNoEffect(MISCREG_FS_EFF_BASE, addr);
return 0;
case GetFS:
fsBase = tc->readMiscRegNoEffect(MISCREG_FS_BASE);
@@ -110,6 +111,7 @@ archPrctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
return 0;
case SetGS:
tc->setMiscRegNoEffect(MISCREG_GS_BASE, addr);
+ tc->setMiscRegNoEffect(MISCREG_GS_EFF_BASE, addr);
return 0;
case GetGS:
gsBase = tc->readMiscRegNoEffect(MISCREG_GS_BASE);
diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc
index 71908098e..a01902478 100644
--- a/src/arch/x86/miscregfile.cc
+++ b/src/arch/x86/miscregfile.cc
@@ -186,6 +186,25 @@ void MiscRegFile::setReg(int miscReg,
break;
case MISCREG_CR8:
break;
+ case MISCREG_CS_ATTR:
+ {
+ SegAttr toggled = regVal[miscReg] ^ val;
+ SegAttr newCSAttr = val;
+ if (toggled.longMode) {
+ SegAttr newCSAttr = val;
+ if (newCSAttr.longMode) {
+ regVal[MISCREG_ES_EFF_BASE] = 0;
+ regVal[MISCREG_CS_EFF_BASE] = 0;
+ regVal[MISCREG_SS_EFF_BASE] = 0;
+ regVal[MISCREG_DS_EFF_BASE] = 0;
+ } else {
+ regVal[MISCREG_ES_EFF_BASE] = regVal[MISCREG_ES_BASE];
+ regVal[MISCREG_CS_EFF_BASE] = regVal[MISCREG_CS_BASE];
+ regVal[MISCREG_SS_EFF_BASE] = regVal[MISCREG_SS_BASE];
+ regVal[MISCREG_DS_EFF_BASE] = regVal[MISCREG_DS_BASE];
+ }
+ }
+ }
}
setRegNoEffect(miscReg, newVal);
}
diff --git a/src/arch/x86/miscregs.hh b/src/arch/x86/miscregs.hh
index 3a30b9800..d3960073a 100644
--- a/src/arch/x86/miscregs.hh
+++ b/src/arch/x86/miscregs.hh
@@ -270,8 +270,20 @@ namespace X86ISA
MISCREG_GS_BASE,
MISCREG_INT_BASE,
+ // The effective segment base, ie what is actually added to an
+ // address. In 64 bit mode this can be different from the above,
+ // namely 0.
+ MISCREG_SEG_EFF_BASE_BASE = MISCREG_SEG_BASE_BASE + NumSegments,
+ MISCREG_ES_EFF_BASE = MISCREG_SEG_EFF_BASE_BASE,
+ MISCREG_CS_EFF_BASE,
+ MISCREG_SS_EFF_BASE,
+ MISCREG_DS_EFF_BASE,
+ MISCREG_FS_EFF_BASE,
+ MISCREG_GS_EFF_BASE,
+ MISCREG_INT_EFF_BASE,
+
// Hidden segment limit field
- MISCREG_SEG_LIMIT_BASE = MISCREG_SEG_BASE_BASE + NumSegments,
+ MISCREG_SEG_LIMIT_BASE = MISCREG_SEG_EFF_BASE_BASE + NumSegments,
MISCREG_ES_LIMIT = MISCREG_SEG_LIMIT_BASE,
MISCREG_CS_LIMIT,
MISCREG_SS_LIMIT,
@@ -407,6 +419,12 @@ namespace X86ISA
}
static inline MiscRegIndex
+ MISCREG_SEG_EFF_BASE(int index)
+ {
+ return (MiscRegIndex)(MISCREG_SEG_EFF_BASE_BASE + index);
+ }
+
+ static inline MiscRegIndex
MISCREG_SEG_LIMIT(int index)
{
return (MiscRegIndex)(MISCREG_SEG_LIMIT_BASE + index);
diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc
index 633b2f136..76f0b5d04 100644
--- a/src/arch/x86/process.cc
+++ b/src/arch/x86/process.cc
@@ -160,6 +160,7 @@ X86LiveProcess::startup()
//Initialize the segment registers.
for(int seg = 0; seg < NUM_SEGMENTREGS; seg++) {
tc->setMiscRegNoEffect(MISCREG_SEG_BASE(seg), 0);
+ tc->setMiscRegNoEffect(MISCREG_SEG_EFF_BASE(seg), 0);
tc->setMiscRegNoEffect(MISCREG_SEG_ATTR(seg), dataAttr);
}
diff --git a/src/arch/x86/utility.cc b/src/arch/x86/utility.cc
index 0153f10e0..69179c1f4 100644
--- a/src/arch/x86/utility.cc
+++ b/src/arch/x86/utility.cc
@@ -118,6 +118,7 @@ void initCPU(ThreadContext *tc, int cpuId)
for (int seg = 0; seg != NUM_SEGMENTREGS; seg++) {
tc->setMiscReg(MISCREG_SEG_SEL(seg), 0);
tc->setMiscReg(MISCREG_SEG_BASE(seg), 0);
+ tc->setMiscReg(MISCREG_SEG_EFF_BASE(seg), 0);
tc->setMiscReg(MISCREG_SEG_LIMIT(seg), 0xffff);
tc->setMiscReg(MISCREG_SEG_ATTR(seg), dataAttr);
}
@@ -130,7 +131,10 @@ void initCPU(ThreadContext *tc, int cpuId)
codeAttr.defaultSize = 0;
tc->setMiscReg(MISCREG_CS, 0xf000);
- tc->setMiscReg(MISCREG_CS_BASE, 0x00000000ffff0000ULL);
+ tc->setMiscReg(MISCREG_CS_BASE,
+ 0x00000000ffff0000ULL);
+ tc->setMiscReg(MISCREG_CS_EFF_BASE,
+ 0x00000000ffff0000ULL);
// This has the base value pre-added.
tc->setMiscReg(MISCREG_CS_LIMIT, 0xffffffff);
tc->setMiscReg(MISCREG_CS_ATTR, codeAttr);