From dc6f96017135da7f3beae5055195de3cf8e47c6c Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 1 Dec 2007 23:03:39 -0800 Subject: [PATCH] X86: Reorganize segmentation and implement segment selector movs. --HG-- extra : convert_revision : 553c3ffeda1f5312cf02493f602e7d4ba2fe66e8 --- src/arch/x86/insts/static_inst.cc | 22 +++- src/arch/x86/isa/decoder/one_byte_opcodes.isa | 16 ++- .../general_purpose/data_transfer/move.py | 102 ++++++++++++++++++ src/arch/x86/isa/insts/system/segmentation.py | 16 +-- src/arch/x86/isa/microasm.isa | 10 +- src/arch/x86/isa/microops/regop.isa | 97 +++++++++++++++-- src/arch/x86/isa/operands.isa | 32 ++++-- src/arch/x86/isa/specialize.isa | 8 +- src/arch/x86/miscregfile.cc | 25 +++++ src/arch/x86/miscregs.hh | 102 ++++++++---------- src/arch/x86/segmentregs.hh | 19 ++-- src/arch/x86/tlb.cc | 4 +- src/arch/x86/utility.cc | 16 +-- 13 files changed, 361 insertions(+), 108 deletions(-) diff --git a/src/arch/x86/insts/static_inst.cc b/src/arch/x86/insts/static_inst.cc index 183700fa9..0c1508d5a 100644 --- a/src/arch/x86/insts/static_inst.cc +++ b/src/arch/x86/insts/static_inst.cc @@ -94,8 +94,26 @@ namespace X86ISA case SEGMENT_REG_GS: ccprintf(os, "GS"); break; - case SEGMENT_REG_INT: - ccprintf(os, "INT"); + case SEGMENT_REG_HS: + ccprintf(os, "HS"); + break; + case SEGMENT_REG_TSL: + ccprintf(os, "TSL"); + break; + case SEGMENT_REG_TSG: + ccprintf(os, "TSG"); + break; + case SEGMENT_REG_LS: + ccprintf(os, "LS"); + break; + case SEGMENT_REG_MS: + ccprintf(os, "MS"); + break; + case SYS_SEGMENT_REG_TR: + ccprintf(os, "TR"); + break; + case SYS_SEGMENT_REG_IDTR: + ccprintf(os, "IDTR"); break; default: panic("Unrecognized segment %d\n", segment); diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa index 62b8c8d59..0d1d7aacd 100644 --- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa @@ -292,9 +292,21 @@ 0x1: MOV(Ev,Gv); 0x2: MOV(Gb,Eb); 0x3: MOV(Gv,Ev); - 0x4: WarnUnimpl::mov_MwRv_Sw(); //What to do with this one? + 0x4: decode MODRM_REG { + 0x0, 0x1, 0x2, + 0x3, 0x4, 0x5: MOV(Ev,Sv); + } 0x5: LEA(Gv,M); - 0x6: WarnUnimpl::mov_Sw_MwRv(); + 0x6: decode MODE_SUBMODE { + 0x3, 0x4: MOV_REAL(Sv,Ev); + default: decode MODRM_REG { + 0x1: UD2(); // Moving to the CS selector is illegal. + 0x2: MOVSS(Sv,Ev); + 0x0, 0x3, + 0x4, 0x5: MOV(Sv,Ev); + default: UD2(); + } + } //0x7: group10_Ev(); 0x7: decode MODRM_REG { 0x0: POP(Ev); diff --git a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py index a15fc21ef..aaddcf962 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py +++ b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py @@ -192,6 +192,108 @@ def macroop MOVZX_W_R_P { def macroop MOV_C_R { wrcr reg, regm }; + +def macroop MOV_R_S { + rdsel reg, regm +}; + +def macroop MOV_M_S { + rdsel t1, reg + st t1, seg, sib, disp, dataSize=2 +}; + +def macroop MOV_P_S { + rdip t7 + rdsel t1, reg + st t1, seg, riprel, disp, dataSize=2 +}; + +def macroop MOV_REAL_S_R { + zext t2, regm, 15 + slli t3, t2, 2, dataSize=8 + wrsel reg, regm + wrbase reg, t3 +}; + +def macroop MOV_REAL_S_M { + ld t1, seg, sib, disp, dataSize=2 + zext t2, t1, 15 + slli t3, t2, 2, dataSize=8 + wrsel reg, t1 + wrbase reg, t3 +}; + +def macroop MOV_REAL_S_P { + rdip t7 + ld t1, seg, riprel, disp, dataSize=2 + zext t2, t1, 15 + slli t3, t2, 2, dataSize=8 + wrsel reg, t1 + wrbase reg, t3 +}; + +def macroop MOV_S_R { + chks t1, regm, flags=(EZF,), dataSize=8 + bri t0, label("end"), flags=(CEZF,) + ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8 + wrdl reg, t2, regm +end: + wrsel reg, regm +}; + +def macroop MOV_S_M { + ld t1, seg, sib, disp, dataSize=2 + chks t2, t1, flags=(EZF,), dataSize=8 + bri t0, label("end"), flags=(CEZF,) + ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8 + wrdl reg, t2, t1 +end: + wrsel reg, t1 +}; + +def macroop MOV_S_P { + rdip t7 + ld t1, seg, riprel, disp, dataSize=2 + chks t2, t1, flags=(EZF,), dataSize=8 + bri t0, label("end"), flags=(CEZF,) + ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8 + wrdl reg, t2, t1 +end: + wrsel reg, t1 +}; + +def macroop MOVSS_S_R { + chks t1, regm, flags=(EZF,), dataSize=8 + # This actually needs to use the selector as the error code, but it would + # be hard to get that information into the instruction at the moment. + fault "new GeneralProtection(0)", flags=(CEZF,) + ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8 + wrdl reg, t2, regm + wrsel reg, regm +}; + +def macroop MOVSS_S_M { + ld t1, seg, sib, disp, dataSize=2 + chks t2, t1, flags=(EZF,), dataSize=8 + # This actually needs to use the selector as the error code, but it would + # be hard to get that information into the instruction at the moment. + fault "new GeneralProtection(0)", flags=(CEZF,) + ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8 + wrdl reg, t2, t1 + wrsel reg, t1 +}; + +def macroop MOVSS_S_P { + rdip t7 + ld t1, seg, riprel, disp, dataSize=2 + chks t2, t1, flags=(EZF,), dataSize=8 + # This actually needs to use the selector as the error code, but it would + # be hard to get that information into the instruction at the moment. + fault "new GeneralProtection(0)", flags=(CEZF,) + ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8 + wrdl reg, t2, t1 + wrsel reg, t1 +}; ''' #let {{ # class MOVD(Inst): diff --git a/src/arch/x86/isa/insts/system/segmentation.py b/src/arch/x86/isa/insts/system/segmentation.py index e46941e53..97846f79c 100644 --- a/src/arch/x86/isa/insts/system/segmentation.py +++ b/src/arch/x86/isa/insts/system/segmentation.py @@ -62,8 +62,8 @@ def macroop LGDT_M ld t1, seg, sib, disp, dataSize=2 # Get the base ld t2, seg, sib, 'adjustedDisp + 2' - wrbase gdtr, t2 - wrlimit gdtr, t1 + wrbase tsg, t2 + wrlimit tsg, t1 }; def macroop LGDT_P @@ -75,8 +75,8 @@ def macroop LGDT_P ld t1, seg, riprel, disp, dataSize=2 # Get the base ld t2, seg, riprel, 'adjustedDisp + 2' - wrbase gdtr, t2 - wrlimit gdtr, t1 + wrbase tsg, t2 + wrlimit tsg, t1 }; # @@ -93,8 +93,8 @@ def macroop LGDT_16_M # Get the base ld t2, seg, sib, 'adjustedDisp + 2', dataSize=4 zexti t2, t2, 23 - wrbase gdtr, t2 - wrlimit gdtr, t1 + wrbase tsg, t2 + wrlimit tsg, t1 }; def macroop LGDT_16_P @@ -107,8 +107,8 @@ def macroop LGDT_16_P # Get the base ld t2, seg, riprel, 'adjustedDisp + 2', dataSize=4 zexti t2, t2, 23 - wrbase gdtr, t2 - wrlimit gdtr, t1 + wrbase tsg, t2 + wrlimit tsg, t1 }; def macroop LIDT_M diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa index 8c499eeed..9e8b65c4e 100644 --- a/src/arch/x86/isa/microasm.isa +++ b/src/arch/x86/isa/microasm.isa @@ -81,9 +81,12 @@ let {{ for letter in ("C", "D", "E", "F", "G", "S"): assembler.symbols["%ss" % letter.lower()] = "SEGMENT_REG_%sS" % letter - for reg in ("LDTR", "TR", "GDTR", "IDTR"): + for reg in ("TR", "IDTR"): assembler.symbols[reg.lower()] = "SYS_SEGMENT_REG_%s" % reg + for reg in ("TSL", "TSG"): + assembler.symbols[reg.lower()] = "SEGMENT_REG_%s" % reg + # Miscellaneous symbols symbols = { "reg" : "env.reg", @@ -112,7 +115,10 @@ let {{ # This segment selects an internal address space mapped to MSRs, # CPUID info, etc. - assembler.symbols["intseg"] = "SEGMENT_REG_INT" + assembler.symbols["intseg"] = "SEGMENT_REG_MS" + # This segment always has base 0, and doesn't imply any special handling + # like the internal segment above + assembler.symbols["flatseg"] = "SEGMENT_REG_LS" for reg in ('ax', 'bx', 'cx', 'dx', 'sp', 'bp', 'si', 'di'): assembler.symbols["r%s" % reg] = "INTREG_R%s" % reg.upper() diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index f37b4327b..7f72fcf1d 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -937,19 +937,100 @@ let {{ } ''' - class Wrbase(RegOp): + # Microops for manipulating segmentation registers + class SegOp(RegOp): + abstract = True def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): - super(Wrbase, self).__init__(dest, \ + super(SegOp, self).__init__(dest, \ src1, "NUM_INTREGS", flags, dataSize) + + class Wrbase(SegOp): code = ''' - SysSegBaseDest = psrc1; + SegBaseDest = psrc1; ''' - class Wrlimit(RegOp): - def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): - super(Wrlimit, self).__init__(dest, \ - src1, "NUM_INTREGS", flags, dataSize) + class Wrlimit(SegOp): + code = ''' + SegLimitDest = psrc1; + ''' + + class Wrsel(SegOp): + code = ''' + SegSelDest = psrc1; + ''' + + class Rdbase(SegOp): + code = ''' + DestReg = SegBaseDest; + ''' + + class Rdlimit(SegOp): + code = ''' + DestReg = SegLimitSrc1; + ''' + + class Rdsel(SegOp): code = ''' - SysSegLimitDest = psrc1; + DestReg = SegSelSrc1; + ''' + + class Chks(SegOp): + code = ''' + // The selector is in source 1. + SegSelector selector = psrc1; + + // Compute the address of the descriptor and set DestReg to it. + if (selector.ti) { + // A descriptor in the LDT + Addr target = (selector.esi << 3) + LDTRBase; + if (!LDTRSel || (selector.esi << 3) + dataSize > LDTRLimit) + fault = new GeneralProtection(selector & mask(16)); + DestReg = target; + } else { + // A descriptor in the GDT + Addr target = (selector.esi << 3) + GDTRBase; + if ((selector.esi << 3) + dataSize > GDTRLimit) + fault = new GeneralProtection(selector & mask(16)); + DestReg = target; + } + ''' + flag_code = ''' + // Check for a NULL selector and set ZF,EZF appropriately. + ccFlagBits = ccFlagBits & ~(ext & (ZFBit | EZFBit)); + if (!selector.esi && !selector.ti) + ccFlagBits = ccFlagBits | (ext & (ZFBit | EZFBit)); + ''' + + class Wrdh(RegOp): + code = ''' + + ''' + + class Wrdl(RegOp): + code = ''' + SegDescriptor desc = SrcReg1; + SegAttr attr = 0; + Addr base = 0, limit = 0; + attr.dpl = desc.dpl; + attr.defaultSize = desc.d; + if (!desc.p) + panic("Segment not present.\\n"); + if (!desc.s) + panic("System segment encountered.\\n"); + if (desc.type.codeOrData) { + panic("Code segment encountered with c = %d, r = %d, a = %d.\\n", + desc.type.c, desc.type.r, desc.type.a); + } else { + attr.expandDown = desc.type.e; + attr.readable = 1; + attr.writable = desc.type.w; + base = desc.baseLow | (desc.baseHigh << 24); + limit = desc.limitLow | (desc.limitHigh << 16); + if (desc.g) + limit = (limit << 12) | mask(12); + } + SegBaseDest = base; + SegLimitDest = limit; + SegAttrDest = attr; ''' }}; diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa index 40c8ee9c2..9345158e9 100644 --- a/src/arch/x86/isa/operands.isa +++ b/src/arch/x86/isa/operands.isa @@ -121,14 +121,30 @@ 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), + # The segment base as used by memory instructions. '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_EFF_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 80), - 'SysSegBaseDest': ('ControlReg', 'uqw', 'MISCREG_SYSSEG_BASE(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 75), - 'SysSegLimitDest': ('ControlReg', 'uqw', 'MISCREG_SYSSEG_LIMIT(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 76), - 'Mem': ('Mem', 'uqw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 100) + # Operands to get and set registers indexed by the operands of the + # original instruction. + 'ControlDest': ('ControlReg', 'uqw', 'MISCREG_CR(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 100), + 'ControlSrc1': ('ControlReg', 'uqw', 'MISCREG_CR(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 101), + 'SegBaseDest': ('ControlReg', 'uqw', 'MISCREG_SEG_BASE(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 102), + 'SegBaseSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_BASE(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 103), + 'SegLimitDest': ('ControlReg', 'uqw', 'MISCREG_SEG_LIMIT(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 104), + 'SegLimitSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_LIMIT(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 105), + 'SegSelDest': ('ControlReg', 'uqw', 'MISCREG_SEG_SEL(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 106), + 'SegSelSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_SEL(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 107), + 'SegAttrDest': ('ControlReg', 'uqw', 'MISCREG_SEG_ATTR(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 108), + 'SegAttrSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_ATTR(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 109), + + # Operands to access specific control registers directly. + 'EferOp': ('ControlReg', 'uqw', 'MISCREG_EFER', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 200), + 'CR4Op': ('ControlReg', 'uqw', 'MISCREG_CR4', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 201), + 'LDTRBase': ('ControlReg', 'uqw', 'MISCREG_TSL_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 202), + 'LDTRLimit': ('ControlReg', 'uqw', 'MISCREG_TSL_LIMIT', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 203), + 'LDTRSel': ('ControlReg', 'uqw', 'MISCREG_TSL', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 204), + 'GDTRBase': ('ControlReg', 'uqw', 'MISCREG_TSG_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 205), + 'GDTRLimit': ('ControlReg', 'uqw', 'MISCREG_TSG_LIMIT', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 206), + 'CSBase': ('ControlReg', 'udw', 'MISCREG_CS_EFF_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 207), + 'Mem': ('Mem', 'uqw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 300) }}; diff --git a/src/arch/x86/isa/specialize.isa b/src/arch/x86/isa/specialize.isa index 3802d8949..abf734307 100644 --- a/src/arch/x86/isa/specialize.isa +++ b/src/arch/x86/isa/specialize.isa @@ -154,12 +154,18 @@ let {{ elif opType.tag == None or opType.size == None: raise Exception, "Problem parsing operand tag: %s" % opType.tag elif opType.tag == "C": + # A control register indexed by the "reg" field env.addReg(ModRMRegIndex) Name += "_C" elif opType.tag == "D": + # A debug register indexed by the "reg" field env.addReg(ModRMRegIndex) Name += "_D" - elif opType.tag in ("G", "P", "S", "T", "V"): + elif opType.tag == "S": + # A segment selector register indexed by the "reg" field + env.addReg(ModRMRegIndex) + Name += "_S" + elif opType.tag in ("G", "P", "T", "V"): # Use the "reg" field of the ModRM byte to select the register env.addReg(ModRMRegIndex) Name += "_R" diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc index a01902478..05d64f73f 100644 --- a/src/arch/x86/miscregfile.cc +++ b/src/arch/x86/miscregfile.cc @@ -205,6 +205,31 @@ void MiscRegFile::setReg(int miscReg, } } } + // These segments always actually use their bases, or in other words + // their effective bases must stay equal to their actual bases. + case MISCREG_FS: + case MISCREG_GS: + case MISCREG_HS: + case MISCREG_TSL: + case MISCREG_TSG: + case MISCREG_TR: + case MISCREG_IDTR: + regVal[MISCREG_SEG_EFF_BASE(miscReg - MISCREG_SEG_SEL_BASE)] = val; + break; + // These segments ignore their bases in 64 bit mode. + // their effective bases must stay equal to their actual bases. + case MISCREG_ES: + case MISCREG_CS: + case MISCREG_SS: + case MISCREG_DS: + { + Efer efer = regVal[MISCREG_EFER]; + SegAttr csAttr = regVal[MISCREG_CS_ATTR]; + if (!efer.lma || !csAttr.longMode) // Check for non 64 bit mode. + regVal[MISCREG_SEG_EFF_BASE(miscReg - + MISCREG_SEG_SEL_BASE)] = val; + } + break; } setRegNoEffect(miscReg, newVal); } diff --git a/src/arch/x86/miscregs.hh b/src/arch/x86/miscregs.hh index d3960073a..36b953526 100644 --- a/src/arch/x86/miscregs.hh +++ b/src/arch/x86/miscregs.hh @@ -58,6 +58,7 @@ #ifndef __ARCH_X86_MISCREGS_HH__ #define __ARCH_X86_MISCREGS_HH__ +#include "arch/x86/segmentregs.hh" #include "arch/x86/x86_traits.hh" #include "base/bitunion.hh" @@ -258,76 +259,83 @@ namespace X86ISA MISCREG_DS, MISCREG_FS, MISCREG_GS, - MISCREG_INT, // This isn't actually used. + MISCREG_HS, + MISCREG_TSL, + MISCREG_TSG, + MISCREG_LS, + MISCREG_MS, + MISCREG_TR, + MISCREG_IDTR, // Hidden segment base field - MISCREG_SEG_BASE_BASE = MISCREG_SEG_SEL_BASE + NumSegments, + MISCREG_SEG_BASE_BASE = MISCREG_SEG_SEL_BASE + NUM_SEGMENTREGS, MISCREG_ES_BASE = MISCREG_SEG_BASE_BASE, MISCREG_CS_BASE, MISCREG_SS_BASE, MISCREG_DS_BASE, MISCREG_FS_BASE, MISCREG_GS_BASE, - MISCREG_INT_BASE, + MISCREG_HS_BASE, + MISCREG_TSL_BASE, + MISCREG_TSG_BASE, + MISCREG_LS_BASE, + MISCREG_MS_BASE, + MISCREG_TR_BASE, + MISCREG_IDTR_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_SEG_EFF_BASE_BASE = MISCREG_SEG_BASE_BASE + NUM_SEGMENTREGS, 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, + MISCREG_HS_EFF_BASE, + MISCREG_TSL_EFF_BASE, + MISCREG_TSG_EFF_BASE, + MISCREG_LS_EFF_BASE, + MISCREG_MS_EFF_BASE, + MISCREG_TR_EFF_BASE, + MISCREG_IDTR_EFF_BASE, // Hidden segment limit field - MISCREG_SEG_LIMIT_BASE = MISCREG_SEG_EFF_BASE_BASE + NumSegments, + MISCREG_SEG_LIMIT_BASE = MISCREG_SEG_EFF_BASE_BASE + NUM_SEGMENTREGS, MISCREG_ES_LIMIT = MISCREG_SEG_LIMIT_BASE, MISCREG_CS_LIMIT, MISCREG_SS_LIMIT, MISCREG_DS_LIMIT, MISCREG_FS_LIMIT, MISCREG_GS_LIMIT, - MISCREG_INT_LIMIT, // This isn't actually used. + MISCREG_HS_LIMIT, + MISCREG_TSL_LIMIT, + MISCREG_TSG_LIMIT, + MISCREG_LS_LIMIT, + MISCREG_MS_LIMIT, + MISCREG_TR_LIMIT, + MISCREG_IDTR_LIMIT, // Hidden segment limit attributes - MISCREG_SEG_ATTR_BASE = MISCREG_SEG_LIMIT_BASE + NumSegments, + MISCREG_SEG_ATTR_BASE = MISCREG_SEG_LIMIT_BASE + NUM_SEGMENTREGS, MISCREG_ES_ATTR = MISCREG_SEG_ATTR_BASE, MISCREG_CS_ATTR, MISCREG_SS_ATTR, MISCREG_DS_ATTR, MISCREG_FS_ATTR, MISCREG_GS_ATTR, - MISCREG_INT_ATTR, // This isn't actually used. - - // System segment selectors - MISCREG_SYSSEG_SEL_BASE = MISCREG_SEG_ATTR_BASE + NumSegments, - MISCREG_LDTR = MISCREG_SYSSEG_SEL_BASE, - MISCREG_TR, - - // Hidden system segment base field - MISCREG_SYSSEG_BASE_BASE = MISCREG_SYSSEG_SEL_BASE + NumSysSegments, - MISCREG_LDTR_BASE = MISCREG_SYSSEG_BASE_BASE, - MISCREG_TR_BASE, - MISCREG_GDTR_BASE, - MISCREG_IDTR_BASE, - - // Hidden system segment limit field - MISCREG_SYSSEG_LIMIT_BASE = MISCREG_SYSSEG_BASE_BASE + NumSysSegments, - MISCREG_LDTR_LIMIT = MISCREG_SYSSEG_LIMIT_BASE, - MISCREG_TR_LIMIT, - MISCREG_GDTR_LIMIT, - MISCREG_IDTR_LIMIT, - - // Hidden system segment attribute field - MISCREG_SYSSEG_ATTR_BASE = MISCREG_SYSSEG_LIMIT_BASE + NumSysSegments, - MISCREG_LDTR_ATTR = MISCREG_SYSSEG_ATTR_BASE, + MISCREG_HS_ATTR, + MISCREG_TSL_ATTR, + MISCREG_TSG_ATTR, + MISCREG_LS_ATTR, + MISCREG_MS_ATTR, MISCREG_TR_ATTR, + MISCREG_IDTR_ATTR, // Floating point control registers - MISCREG_X87_TOP = MISCREG_SYSSEG_ATTR_BASE + NumSysSegments, + MISCREG_X87_TOP = + MISCREG_SEG_ATTR_BASE + NUM_SEGMENTREGS, //XXX Add "Model-Specific Registers" @@ -436,30 +444,6 @@ namespace X86ISA return (MiscRegIndex)(MISCREG_SEG_ATTR_BASE + index); } - static inline MiscRegIndex - MISCREG_SYSSEG_SEL(int index) - { - return (MiscRegIndex)(MISCREG_SYSSEG_SEL_BASE + index); - } - - static inline MiscRegIndex - MISCREG_SYSSEG_BASE(int index) - { - return (MiscRegIndex)(MISCREG_SYSSEG_BASE_BASE + index); - } - - static inline MiscRegIndex - MISCREG_SYSSEG_LIMIT(int index) - { - return (MiscRegIndex)(MISCREG_SYSSEG_LIMIT_BASE + index); - } - - static inline MiscRegIndex - MISCREG_SYSSEG_ATTR(int index) - { - return (MiscRegIndex)(MISCREG_SYSSEG_ATTR_BASE + index); - } - /** * A type to describe the condition code bits of the RFLAGS register, * plus two flags, EZF and ECF, which are only visible to microcode. @@ -729,6 +713,10 @@ namespace X86ISA * Segment Selector */ BitUnion64(SegSelector) + // The following bitfield is not defined in the ISA, but it's useful + // when checking selectors in larger data types to make sure they + // aren't too large. + Bitfield<63, 3> esi; // Extended selector Bitfield<15, 3> si; // Selector Index Bitfield<2> ti; // Table Indicator Bitfield<1, 0> rpl; // Requestor Privilege Level diff --git a/src/arch/x86/segmentregs.hh b/src/arch/x86/segmentregs.hh index e6079da6d..7473c5ea9 100644 --- a/src/arch/x86/segmentregs.hh +++ b/src/arch/x86/segmentregs.hh @@ -68,19 +68,18 @@ namespace X86ISA SEGMENT_REG_DS, SEGMENT_REG_FS, SEGMENT_REG_GS, - SEGMENT_REG_INT, - - NUM_SEGMENTREGS - }; - - enum SysSegmentRegIndex - { - SYS_SEGMENT_REG_LDTR, + SEGMENT_REG_HS, // Temporary descriptor + SEGMENT_REG_TSL, // Local descriptor table + SEGMENT_REG_TSG, // Global descriptor table + SEGMENT_REG_LS, // Flat segment + SEGMENT_REG_MS, // Emulation memory + // These shouldn't be used directly in a load or store since they + // are likely accessed in other ways in a real machine. For instance, + // they may be loaded into the temporary segment register on demand. SYS_SEGMENT_REG_TR, - SYS_SEGMENT_REG_GDTR, SYS_SEGMENT_REG_IDTR, - NUM_SYSSEGMENTREGS + NUM_SEGMENTREGS }; }; diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index 68a22bc16..08c621615 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -176,14 +176,14 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) uint32_t flags = req->getFlags(); bool storeCheck = flags & StoreCheck; - int seg = flags & mask(3); + int seg = flags & mask(4); //XXX Junk code to surpress the warning if (storeCheck); // If this is true, we're dealing with a request to read an internal // value. - if (seg == SEGMENT_REG_INT) { + if (seg == SEGMENT_REG_MS) { DPRINTF(TLB, "Addresses references internal memory.\n"); Addr prefix = vaddr & IntAddrPrefixMask; if (prefix == IntAddrPrefixCPUID) { diff --git a/src/arch/x86/utility.cc b/src/arch/x86/utility.cc index 69179c1f4..f45d9083b 100644 --- a/src/arch/x86/utility.cc +++ b/src/arch/x86/utility.cc @@ -143,16 +143,16 @@ void initCPU(ThreadContext *tc, int cpuId) tc->readMiscReg(MISCREG_CS_BASE)); tc->setNextPC(tc->readPC() + sizeof(MachInst)); - tc->setMiscReg(MISCREG_GDTR_BASE, 0); - tc->setMiscReg(MISCREG_GDTR_LIMIT, 0xffff); + tc->setMiscReg(MISCREG_TSG_BASE, 0); + tc->setMiscReg(MISCREG_TSG_LIMIT, 0xffff); tc->setMiscReg(MISCREG_IDTR_BASE, 0); tc->setMiscReg(MISCREG_IDTR_LIMIT, 0xffff); - tc->setMiscReg(MISCREG_LDTR, 0); - tc->setMiscReg(MISCREG_LDTR_BASE, 0); - tc->setMiscReg(MISCREG_LDTR_LIMIT, 0xffff); - tc->setMiscReg(MISCREG_LDTR_ATTR, 0); + tc->setMiscReg(MISCREG_TSL, 0); + tc->setMiscReg(MISCREG_TSL_BASE, 0); + tc->setMiscReg(MISCREG_TSL_LIMIT, 0xffff); + tc->setMiscReg(MISCREG_TSL_ATTR, 0); tc->setMiscReg(MISCREG_TR, 0); tc->setMiscReg(MISCREG_TR_BASE, 0); @@ -306,8 +306,8 @@ void startupCPU(ThreadContext *tc, int cpuId) uint64_t csDescVal = csDesc; physPort->writeBlob(GDTBase, (uint8_t *)(&csDescVal), 8); - tc->setMiscReg(MISCREG_GDTR_BASE, GDTBase); - tc->setMiscReg(MISCREG_GDTR_LIMIT, 0xF); + tc->setMiscReg(MISCREG_TSG_BASE, GDTBase); + tc->setMiscReg(MISCREG_TSG_LIMIT, 0xF); /* * Identity map the first 4GB of memory. In order to map this region -- 2.30.2