From bfc62d1a7035dfdbad405c0ddbd897ea1174360d Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 1 Dec 2007 23:00:15 -0800 Subject: X86: Separate the effective seg base and the "hidden" seg base. --HG-- extra : convert_revision : 5fcb8d94dbab7a7d6fe797277a5856903c885ad4 --- src/arch/x86/isa/operands.isa | 4 ++-- src/arch/x86/linux/syscalls.cc | 2 ++ src/arch/x86/miscregfile.cc | 19 +++++++++++++++++++ src/arch/x86/miscregs.hh | 20 +++++++++++++++++++- src/arch/x86/process.cc | 1 + src/arch/x86/utility.cc | 6 +++++- 6 files changed, 48 insertions(+), 4 deletions(-) (limited to 'src/arch') 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, @@ -406,6 +418,12 @@ namespace X86ISA return (MiscRegIndex)(MISCREG_SEG_BASE_BASE + index); } + 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) { 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); -- cgit v1.2.3