diff --git a/SConstruct b/SConstruct index bfd93f26f..7a0bf2794 100644 --- a/SConstruct +++ b/SConstruct @@ -394,7 +394,7 @@ if main['GCC'] + main['SUNCC'] + main['ICC'] > 1: if main['GCC']: main.Append(CCFLAGS='-pipe') main.Append(CCFLAGS='-fno-strict-aliasing') - main.Append(CCFLAGS=Split('-Wall -Wno-sign-compare -Werror -Wundef')) + main.Append(CCFLAGS=['-Wall', '-Wno-sign-compare', '-Wundef']) main.Append(CXXFLAGS='-Wno-deprecated') elif main['ICC']: pass #Fix me... add warning flags once we clean up icc warnings diff --git a/src/SConscript b/src/SConscript index 20d454f03..d36f5f244 100644 --- a/src/SConscript +++ b/src/SConscript @@ -29,6 +29,7 @@ # Authors: Nathan Binkert import array +import bisect import imp import marshal import os @@ -50,122 +51,144 @@ Export('env') build_env = dict([(opt, env[opt]) for opt in export_vars]) -def sort_list(_list): - """return a sorted copy of '_list'""" - if isinstance(_list, list): - _list = _list[:] - else: - _list = list(_list) - _list.sort() - return _list +######################################################################## +# Code for adding source files of various types +# +class SourceMeta(type): + def __init__(cls, name, bases, dict): + super(SourceMeta, cls).__init__(name, bases, dict) + cls.all = [] + + def get(cls, **kwargs): + for src in cls.all: + for attr,value in kwargs.iteritems(): + if getattr(src, attr) != value: + break + else: + yield src -class PySourceFile(object): +class SourceFile(object): + __metaclass__ = SourceMeta + def __init__(self, source): + tnode = source + if not isinstance(source, SCons.Node.FS.File): + tnode = File(source) + + self.tnode = tnode + self.snode = tnode.srcnode() + self.filename = str(tnode) + self.dirname = dirname(self.filename) + self.basename = basename(self.filename) + index = self.basename.rfind('.') + if index <= 0: + # dot files aren't extensions + self.extname = self.basename, None + else: + self.extname = self.basename[:index], self.basename[index+1:] + + for base in type(self).__mro__: + if issubclass(base, SourceFile): + bisect.insort_right(base.all, self) + + def __lt__(self, other): return self.filename < other.filename + def __le__(self, other): return self.filename <= other.filename + def __gt__(self, other): return self.filename > other.filename + def __ge__(self, other): return self.filename >= other.filename + def __eq__(self, other): return self.filename == other.filename + def __ne__(self, other): return self.filename != other.filename + +class Source(SourceFile): + '''Add a c/c++ source file to the build''' + def __init__(self, source, Werror=True, swig=False, bin_only=False, + skip_lib=False): + super(Source, self).__init__(source) + + self.Werror = Werror + self.swig = swig + self.bin_only = bin_only + self.skip_lib = bin_only or skip_lib + +class PySource(SourceFile): + '''Add a python source file to the named package''' invalid_sym_char = re.compile('[^A-z0-9_]') - def __init__(self, package, tnode): - snode = tnode.srcnode() - filename = str(tnode) - pyname = basename(filename) - assert pyname.endswith('.py') - name = pyname[:-3] + modules = {} + tnodes = {} + symnames = {} + + def __init__(self, package, source): + super(PySource, self).__init__(source) + + modname,ext = self.extname + assert ext == 'py' + if package: path = package.split('.') else: path = [] modpath = path[:] - if name != '__init__': - modpath += [name] + if modname != '__init__': + modpath += [ modname ] modpath = '.'.join(modpath) - arcpath = path + [ pyname ] - arcname = joinpath(*arcpath) - - debugname = snode.abspath + arcpath = path + [ self.basename ] + debugname = self.snode.abspath if not exists(debugname): - debugname = tnode.abspath + debugname = self.tnode.abspath - self.tnode = tnode - self.snode = snode - self.pyname = pyname self.package = package + self.modname = modname self.modpath = modpath - self.arcname = arcname + self.arcname = joinpath(*arcpath) self.debugname = debugname - self.compiled = File(filename + 'c') - self.assembly = File(filename + '.s') - self.symname = "PyEMB_" + self.invalid_sym_char.sub('_', modpath) - + self.compiled = File(self.filename + 'c') + self.assembly = File(self.filename + '.s') + self.symname = "PyEMB_" + PySource.invalid_sym_char.sub('_', modpath) -######################################################################## -# Code for adding source files of various types -# -cc_lib_sources = [] -def Source(source): - '''Add a source file to the libm5 build''' - if not isinstance(source, SCons.Node.FS.File): - source = File(source) + PySource.modules[modpath] = self + PySource.tnodes[self.tnode] = self + PySource.symnames[self.symname] = self - cc_lib_sources.append(source) - -cc_bin_sources = [] -def BinSource(source): - '''Add a source file to the m5 binary build''' - if not isinstance(source, SCons.Node.FS.File): - source = File(source) - - cc_bin_sources.append(source) - -py_sources = [] -def PySource(package, source): - '''Add a python source file to the named package''' - if not isinstance(source, SCons.Node.FS.File): - source = File(source) - - source = PySourceFile(package, source) - py_sources.append(source) - -sim_objects_fixed = False -sim_object_modfiles = set() -def SimObject(source): +class SimObject(PySource): '''Add a SimObject python file as a python source object and add it to a list of sim object modules''' - if sim_objects_fixed: - raise AttributeError, "Too late to call SimObject now." + fixed = False + modnames = [] - if not isinstance(source, SCons.Node.FS.File): - source = File(source) + def __init__(self, source): + super(SimObject, self).__init__('m5.objects', source) + if self.fixed: + raise AttributeError, "Too late to call SimObject now." - PySource('m5.objects', source) - modfile = basename(str(source)) - assert modfile.endswith('.py') - modname = modfile[:-3] - sim_object_modfiles.add(modname) + bisect.insort_right(SimObject.modnames, self.modname) -swig_sources = [] -def SwigSource(package, source): +class SwigSource(SourceFile): '''Add a swig file to build''' - if not isinstance(source, SCons.Node.FS.File): - source = File(source) - val = source,package - swig_sources.append(val) + + def __init__(self, package, source): + super(SwigSource, self).__init__(source) + + modname,ext = self.extname + assert ext == 'i' + + self.module = modname + cc_file = joinpath(self.dirname, modname + '_wrap.cc') + py_file = joinpath(self.dirname, modname + '.py') + + self.cc_source = Source(cc_file, swig=True) + self.py_source = PySource(package, py_file) unit_tests = [] def UnitTest(target, sources): if not isinstance(sources, (list, tuple)): sources = [ sources ] - - srcs = [] - for source in sources: - if not isinstance(source, SCons.Node.FS.File): - source = File(source) - srcs.append(source) - - unit_tests.append((target, srcs)) + + sources = [ Source(src, skip_lib=True) for src in sources ] + unit_tests.append((target, sources)) # Children should have access Export('Source') -Export('BinSource') Export('PySource') Export('SimObject') Export('SwigSource') @@ -276,7 +299,8 @@ class DictImporter(object): if fullname.startswith('m5.internal'): return None - if fullname in self.modules and exists(self.modules[fullname]): + source = self.modules.get(fullname, None) + if source is not None and exists(source.snode.abspath): return self return None @@ -295,34 +319,28 @@ class DictImporter(object): mod.__dict__['buildEnv'] = build_env return mod - srcfile = self.modules[fullname] - if basename(srcfile) == '__init__.py': - mod.__path__ = fullname.split('.') - mod.__file__ = srcfile + source = self.modules[fullname] + if source.modname == '__init__': + mod.__path__ = source.modpath + mod.__file__ = source.snode.abspath - exec file(srcfile, 'r') in mod.__dict__ + exec file(source.snode.abspath, 'r') in mod.__dict__ return mod -py_modules = {} -for source in py_sources: - py_modules[source.modpath] = source.snode.abspath - # install the python importer so we can grab stuff from the source # tree itself. We can't have SimObjects added after this point or # else we won't know about them for the rest of the stuff. -sim_objects_fixed = True -importer = DictImporter(py_modules) +SimObject.fixed = True +importer = DictImporter(PySource.modules) sys.meta_path[0:0] = [ importer ] import m5 # import all sim objects so we can populate the all_objects list # make sure that we're working with a list, then let's sort it -sim_objects = list(sim_object_modfiles) -sim_objects.sort() -for simobj in sim_objects: - exec('from m5.objects import %s' % simobj) +for modname in SimObject.modnames: + exec('from m5.objects import %s' % modname) # we need to unload all of the currently imported modules so that they # will be re-imported the next time the sconscript is run @@ -333,7 +351,7 @@ sim_objects = m5.SimObject.allClasses all_enums = m5.params.allEnums all_params = {} -for name,obj in sim_objects.iteritems(): +for name,obj in sorted(sim_objects.iteritems()): for param in obj._params.local.values(): if not hasattr(param, 'swig_decl'): continue @@ -346,7 +364,7 @@ for name,obj in sim_objects.iteritems(): # calculate extra dependencies # module_depends = ["m5", "m5.SimObject", "m5.params"] -depends = [ File(py_modules[dep]) for dep in module_depends ] +depends = [ PySource.modules[dep].tnode for dep in module_depends ] ######################################################################## # @@ -392,7 +410,7 @@ def makeObjectsInitFile(target, source, env): # Generate an __init__.py file for the objects package env.Command('python/m5/objects/__init__.py', - [ Value(o) for o in sort_list(sim_object_modfiles) ], + map(Value, SimObject.modnames), makeObjectsInitFile) PySource('m5.objects', 'python/m5/objects/__init__.py') @@ -409,6 +427,7 @@ def createSimObjectParam(target, source, env): obj = sim_objects[name] print >>hh_file, obj.cxx_decl() + hh_file.close() def createSwigParam(target, source, env): assert len(target) == 1 and len(source) == 1 @@ -419,6 +438,7 @@ def createSwigParam(target, source, env): for line in param.swig_decl(): print >>i_file, line + i_file.close() def createEnumStrings(target, source, env): assert len(target) == 1 and len(source) == 1 @@ -438,11 +458,13 @@ def createEnumParam(target, source, env): obj = all_enums[name] print >>hh_file, obj.cxx_decl() + hh_file.close() # Generate all of the SimObject param struct header files params_hh_files = [] -for name,simobj in sim_objects.iteritems(): - extra_deps = [ File(py_modules[simobj.__module__]) ] +for name,simobj in sorted(sim_objects.iteritems()): + py_source = PySource.modules[simobj.__module__] + extra_deps = [ py_source.tnode ] hh_file = File('params/%s.hh' % name) params_hh_files.append(hh_file) @@ -463,8 +485,9 @@ for name,param in all_params.iteritems(): env.Depends(i_file, depends) # Generate all enum header files -for name,enum in all_enums.iteritems(): - extra_deps = [ File(py_modules[enum.__module__]) ] +for name,enum in sorted(all_enums.iteritems()): + py_source = PySource.modules[enum.__module__] + extra_deps = [ py_source.tnode ] cc_file = File('enums/%s.cc' % name) env.Command(cc_file, Value(name), createEnumStrings) @@ -576,32 +599,18 @@ def buildParams(target, source, env): print >>out, '%%include "params/%s.hh"' % obj params_file = File('params/params.i') -names = sort_list(sim_objects.keys()) -env.Command(params_file, [ Value(v) for v in names ], buildParams) +names = sorted(sim_objects.keys()) +env.Command(params_file, map(Value, names), buildParams) env.Depends(params_file, params_hh_files + params_i_files + depends) SwigSource('m5.objects', params_file) # Build all swig modules -swig_modules = [] -cc_swig_sources = [] -for source,package in swig_sources: - filename = str(source) - assert filename.endswith('.i') - - base = '.'.join(filename.split('.')[:-1]) - module = basename(base) - cc_file = base + '_wrap.cc' - py_file = base + '.py' - - env.Command([cc_file, py_file], source, +for swig in SwigSource.all: + env.Command([swig.cc_source.tnode, swig.py_source.tnode], swig.tnode, '$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} ' '-o ${TARGETS[0]} $SOURCES') - env.Depends(py_file, source) - env.Depends(cc_file, source) - - swig_modules.append(Value(module)) - cc_swig_sources.append(File(cc_file)) - PySource(package, py_file) + env.Depends(swig.py_source.tnode, swig.tnode) + env.Depends(swig.cc_source.tnode, swig.tnode) # Generate the main swig init file def makeSwigInit(target, source, env): @@ -616,7 +625,9 @@ def makeSwigInit(target, source, env): print >>f, '}' f.close() -env.Command('python/swig/init.cc', swig_modules, makeSwigInit) +env.Command('python/swig/init.cc', + map(Value, sorted(s.module for s in SwigSource.all)), + makeSwigInit) Source('python/swig/init.cc') # Generate traceflags.py @@ -813,7 +824,7 @@ extern const Flags *compoundFlags[]; f.close() -flags = [ Value(f) for f in trace_flags.values() ] +flags = map(Value, trace_flags.values()) env.Command('base/traceflags.py', flags, traceFlagsPy) PySource('m5', 'base/traceflags.py') @@ -827,10 +838,6 @@ Source('base/traceflags.cc') # byte code, compress it, and then generate an assembly file that # inserts the result into the data section with symbols indicating the # beginning, and end (and with the size at the end) -py_sources_tnodes = {} -for pysource in py_sources: - py_sources_tnodes[pysource.tnode] = pysource - def objectifyPyFile(target, source, env): '''Action function to compile a .py into a code object, marshal it, compress it, and stick it into an asm file so the code appears @@ -839,7 +846,7 @@ def objectifyPyFile(target, source, env): src = file(str(source[0]), 'r').read() dst = file(str(target[0]), 'w') - pysource = py_sources_tnodes[source[0]] + pysource = PySource.tnodes[source[0]] compiled = compile(src, pysource.debugname, 'exec') marshalled = marshal.dumps(compiled) compressed = zlib.compress(marshalled) @@ -864,7 +871,7 @@ def objectifyPyFile(target, source, env): print >>dst, "%s_end:" % sym print >>dst, ".long %d" % len(marshalled) -for source in py_sources: +for source in PySource.all: env.Command(source.assembly, source.tnode, objectifyPyFile) Source(source.assembly) @@ -873,14 +880,11 @@ for source in py_sources: # contains information about the importer that python uses to get at # the embedded files, and then there's a list of all of the rest that # the importer uses to load the rest on demand. -py_sources_symbols = {} -for pysource in py_sources: - py_sources_symbols[pysource.symname] = pysource def pythonInit(target, source, env): dst = file(str(target[0]), 'w') def dump_mod(sym, endchar=','): - pysource = py_sources_symbols[sym] + pysource = PySource.symnames[sym] print >>dst, ' { "%s",' % pysource.arcname print >>dst, ' "%s",' % pysource.modpath print >>dst, ' %s_beg, %s_end,' % (sym, sym) @@ -907,8 +911,10 @@ def pythonInit(target, source, env): print >>dst, " { 0, 0, 0, 0, 0, 0 }" print >>dst, "};" -symbols = [Value(s.symname) for s in py_sources] -env.Command('sim/init_python.cc', symbols, pythonInit) + +env.Command('sim/init_python.cc', + map(Value, (s.symname for s in PySource.all)), + pythonInit) Source('sim/init_python.cc') ######################################################################## @@ -920,26 +926,7 @@ Source('sim/init_python.cc') # List of constructed environments to pass back to SConstruct envList = [] -# This function adds the specified sources to the given build -# environment, and returns a list of all the corresponding SCons -# Object nodes (including an extra one for date.cc). We explicitly -# add the Object nodes so we can set up special dependencies for -# date.cc. -def make_objs(sources, env, static): - if static: - XObject = env.StaticObject - else: - XObject = env.SharedObject - - objs = [ XObject(s) for s in sources ] - - # make date.cc depend on all other objects so it always gets - # recompiled whenever anything else does - date_obj = XObject('base/date.cc') - - env.Depends(date_obj, objs) - objs.append(date_obj) - return objs +date_source = Source('base/date.cc', skip_lib=True) # Function to create a new build environment as clone of current # environment 'env' with modified object suffix and optional stripped @@ -956,15 +943,45 @@ def makeEnv(label, objsfx, strip = False, **kwargs): new_env.Append(**kwargs) swig_env = new_env.Clone() + swig_env.Append(CCFLAGS='-Werror') if env['GCC']: swig_env.Append(CCFLAGS='-Wno-uninitialized') swig_env.Append(CCFLAGS='-Wno-sign-compare') swig_env.Append(CCFLAGS='-Wno-parentheses') - static_objs = make_objs(cc_lib_sources, new_env, static=True) - shared_objs = make_objs(cc_lib_sources, new_env, static=False) - static_objs += [ swig_env.StaticObject(s) for s in cc_swig_sources ] - shared_objs += [ swig_env.SharedObject(s) for s in cc_swig_sources ] + werror_env = new_env.Clone() + werror_env.Append(CCFLAGS='-Werror') + + def make_obj(source, static, extra_deps = None): + '''This function adds the specified source to the correct + build environment, and returns the corresponding SCons Object + nodes''' + + if source.swig: + env = swig_env + elif source.Werror: + env = werror_env + else: + env = new_env + + if static: + obj = env.StaticObject(source.tnode) + else: + obj = env.SharedObject(source.tnode) + + if extra_deps: + env.Depends(obj, extra_deps) + + return obj + + static_objs = [ make_obj(s, True) for s in Source.get(skip_lib=False)] + shared_objs = [ make_obj(s, False) for s in Source.get(skip_lib=False)] + + static_date = make_obj(date_source, static=True, extra_deps=static_objs) + static_objs.append(static_date) + + shared_date = make_obj(date_source, static=False, extra_deps=shared_objs) + shared_objs.append(static_date) # First make a library of everything but main() so other programs can # link against m5. @@ -972,21 +989,23 @@ def makeEnv(label, objsfx, strip = False, **kwargs): shared_lib = new_env.SharedLibrary(libname, shared_objs) for target, sources in unit_tests: - objs = [ new_env.StaticObject(s) for s in sources ] + objs = [ make_obj(s, static=True) for s in sources ] new_env.Program("unittest/%s.%s" % (target, label), objs + static_objs) # Now link a stub with main() and the static library. - objects = [new_env.Object(s) for s in cc_bin_sources] + static_objs + bin_objs = [make_obj(s, True) for s in Source.get(bin_only=True) ] + progname = exename + if strip: + progname += '.unstripped' + + targets = new_env.Program(progname, bin_objs + static_objs) + if strip: - unstripped_exe = exename + '.unstripped' - new_env.Program(unstripped_exe, objects) if sys.platform == 'sunos5': cmd = 'cp $SOURCE $TARGET; strip $TARGET' else: cmd = 'strip $SOURCE -o $TARGET' - targets = new_env.Command(exename, unstripped_exe, cmd) - else: - targets = new_env.Program(exename, objects) + targets = new_env.Command(exename, progname, cmd) new_env.M5Binary = targets[0] envList.append(new_env) diff --git a/src/arch/x86/faults.cc b/src/arch/x86/faults.cc index bef7e4414..10b539248 100644 --- a/src/arch/x86/faults.cc +++ b/src/arch/x86/faults.cc @@ -271,12 +271,8 @@ namespace X86ISA tc->setMiscReg(MISCREG_DR6, 0x00000000ffff0ff0ULL); tc->setMiscReg(MISCREG_DR7, 0x0000000000000400ULL); - // We're now in real mode, effectively at CPL 0 - HandyM5Reg m5Reg = 0; - m5Reg.mode = LegacyMode; - m5Reg.submode = RealMode; - m5Reg.cpl = 0; - tc->setMiscReg(MISCREG_M5_REG, m5Reg); + // Update the handy M5 Reg. + tc->setMiscReg(MISCREG_M5_REG, 0); MicroPC entry = X86ISAInst::RomLabels::extern_label_initIntHalt; tc->setMicroPC(romMicroPC(entry)); tc->setNextMicroPC(romMicroPC(entry) + 1); @@ -289,7 +285,7 @@ namespace X86ISA HandyM5Reg m5Reg = tc->readMiscReg(MISCREG_M5_REG); if (m5Reg.mode != LegacyMode || m5Reg.submode != RealMode) { panic("Startup IPI recived outside of real mode. " - "Don't know what to do."); + "Don't know what to do. %d, %d", m5Reg.mode, m5Reg.submode); } tc->setMiscReg(MISCREG_CS, vector << 8); diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc index 0316603e5..317cdadc5 100644 --- a/src/arch/x86/miscregfile.cc +++ b/src/arch/x86/miscregfile.cc @@ -96,6 +96,64 @@ using namespace std; class Checkpoint; +void MiscRegFile::updateHandyM5Reg(Efer efer, CR0 cr0, + SegAttr csAttr, SegAttr ssAttr, RFLAGS rflags) +{ + HandyM5Reg m5reg; + if (efer.lma) { + m5reg.mode = LongMode; + if (csAttr.longMode) + m5reg.submode = SixtyFourBitMode; + else + m5reg.submode = CompatabilityMode; + } else { + m5reg.mode = LegacyMode; + if (cr0.pe) { + if (rflags.vm) + m5reg.submode = Virtual8086Mode; + else + m5reg.submode = ProtectedMode; + } else { + m5reg.submode = RealMode; + } + } + m5reg.cpl = csAttr.dpl; + m5reg.paging = cr0.pg; + m5reg.prot = cr0.pe; + + // Compute the default and alternate operand size. + if (m5reg.submode == SixtyFourBitMode || csAttr.defaultSize) { + m5reg.defOp = 2; + m5reg.altOp = 1; + } else { + m5reg.defOp = 1; + m5reg.altOp = 2; + } + + // Compute the default and alternate address size. + if (m5reg.submode == SixtyFourBitMode) { + m5reg.defAddr = 3; + m5reg.altAddr = 2; + } else if (csAttr.defaultSize) { + m5reg.defAddr = 2; + m5reg.altAddr = 1; + } else { + m5reg.defAddr = 1; + m5reg.altAddr = 2; + } + + // Compute the stack size + if (m5reg.submode == SixtyFourBitMode) { + m5reg.stack = 3; + } else if (ssAttr.defaultSize) { + m5reg.stack = 2; + } else { + m5reg.stack = 1; + } + + regVal[MISCREG_M5_REG] = m5reg; +} + void MiscRegFile::clear() { // Blank everything. 0 might not be an appropriate value for some things, @@ -151,39 +209,17 @@ void MiscRegFile::setReg(MiscRegIndex miscReg, CR0 toggled = regVal[miscReg] ^ val; CR0 newCR0 = val; Efer efer = regVal[MISCREG_EFER]; - HandyM5Reg m5reg = regVal[MISCREG_M5_REG]; if (toggled.pg && efer.lme) { if (newCR0.pg) { //Turning on long mode efer.lma = 1; - m5reg.mode = LongMode; regVal[MISCREG_EFER] = efer; } else { //Turning off long mode efer.lma = 0; - m5reg.mode = LegacyMode; regVal[MISCREG_EFER] = efer; } } - // Figure out what submode we're in. - if (m5reg.mode == LongMode) { - SegAttr csAttr = regVal[MISCREG_CS_ATTR]; - if (csAttr.longMode) - m5reg.submode = SixtyFourBitMode; - else - m5reg.submode = CompatabilityMode; - } else { - if (newCR0.pe) { - RFLAGS rflags = regVal[MISCREG_RFLAGS]; - if (rflags.vm) - m5reg.submode = Virtual8086Mode; - else - m5reg.submode = ProtectedMode; - } else { - m5reg.submode = RealMode; - } - } - regVal[MISCREG_M5_REG] = m5reg; if (toggled.pg) { tc->getITBPtr()->invalidateAll(); tc->getDTBPtr()->invalidateAll(); @@ -191,6 +227,11 @@ void MiscRegFile::setReg(MiscRegIndex miscReg, //This must always be 1. newCR0.et = 1; newVal = newCR0; + updateHandyM5Reg(regVal[MISCREG_EFER], + newCR0, + regVal[MISCREG_CS_ATTR], + regVal[MISCREG_SS_ATTR], + regVal[MISCREG_RFLAGS]); } break; case MISCREG_CR2: @@ -214,28 +255,33 @@ void MiscRegFile::setReg(MiscRegIndex miscReg, { SegAttr toggled = regVal[miscReg] ^ val; SegAttr newCSAttr = val; - HandyM5Reg m5reg = regVal[MISCREG_M5_REG]; if (toggled.longMode) { if (newCSAttr.longMode) { - if (m5reg.mode == LongMode) - m5reg.submode = SixtyFourBitMode; 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 { - if (m5reg.mode == LongMode) - m5reg.submode = CompatabilityMode; 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]; } } - m5reg.cpl = newCSAttr.dpl; - regVal[MISCREG_M5_REG] = m5reg; + updateHandyM5Reg(regVal[MISCREG_EFER], + regVal[MISCREG_CR0], + newCSAttr, + regVal[MISCREG_SS_ATTR], + regVal[MISCREG_RFLAGS]); } break; + case MISCREG_SS_ATTR: + updateHandyM5Reg(regVal[MISCREG_EFER], + regVal[MISCREG_CR0], + regVal[MISCREG_CS_ATTR], + val, + regVal[MISCREG_RFLAGS]); + break; // These segments always actually use their bases, or in other words // their effective bases must stay equal to their actual bases. case MISCREG_FS_BASE: @@ -333,6 +379,16 @@ void MiscRegFile::setReg(MiscRegIndex miscReg, dr7.len3 = newDR7.len3; } break; + case MISCREG_M5_REG: + // Writing anything to the m5reg with side effects makes it update + // based on the current values of the relevant registers. The actual + // value written is discarded. + updateHandyM5Reg(regVal[MISCREG_EFER], + regVal[MISCREG_CR0], + regVal[MISCREG_CS_ATTR], + regVal[MISCREG_SS_ATTR], + regVal[MISCREG_RFLAGS]); + return; default: break; } diff --git a/src/arch/x86/miscregfile.hh b/src/arch/x86/miscregfile.hh index 6d3ae4e92..babc65b44 100644 --- a/src/arch/x86/miscregfile.hh +++ b/src/arch/x86/miscregfile.hh @@ -107,6 +107,8 @@ namespace X86ISA { protected: MiscReg regVal[NumMiscRegs]; + void updateHandyM5Reg(Efer efer, CR0 cr0, + SegAttr csAttr, SegAttr ssAttr, RFLAGS rflags); public: void clear(); diff --git a/src/arch/x86/miscregs.hh b/src/arch/x86/miscregs.hh index af02e9422..088dbeace 100644 --- a/src/arch/x86/miscregs.hh +++ b/src/arch/x86/miscregs.hh @@ -518,6 +518,13 @@ namespace X86ISA Bitfield<0> mode; Bitfield<3, 1> submode; Bitfield<5, 4> cpl; + Bitfield<6> paging; + Bitfield<7> prot; + Bitfield<9, 8> defOp; + Bitfield<11, 10> altOp; + Bitfield<13, 12> defAddr; + Bitfield<15, 14> altAddr; + Bitfield<17, 16> stack; EndBitUnion(HandyM5Reg) /** diff --git a/src/arch/x86/predecoder.cc b/src/arch/x86/predecoder.cc index 620ab89ea..5bac8e711 100644 --- a/src/arch/x86/predecoder.cc +++ b/src/arch/x86/predecoder.cc @@ -80,9 +80,9 @@ namespace X86ISA emi.modRM = 0; emi.sib = 0; - HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); - emi.mode.mode = m5reg.mode; - emi.mode.submode = m5reg.submode; + m5Reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); + emi.mode.mode = m5Reg.mode; + emi.mode.submode = m5Reg.submode; } void Predecoder::process() @@ -216,34 +216,15 @@ namespace X86ISA DPRINTF(Predecoder, "Found opcode %#x.\n", nextByte); emi.opcode.op = nextByte; - SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR); - //Figure out the effective operand size. This can be overriden to //a fixed value at the decoder level. int logOpSize; - if (emi.mode.submode == SixtyFourBitMode) - { - if(emi.rex.w) - logOpSize = 3; // 64 bit operand size - else if(emi.legacy.op) - logOpSize = 1; // 16 bit operand size - else - logOpSize = 2; // 32 bit operand size - } - else if(csAttr.defaultSize) - { - if(emi.legacy.op) - logOpSize = 1; // 16 bit operand size - else - logOpSize = 2; // 32 bit operand size - } - else // 16 bit default operand size - { - if(emi.legacy.op) - logOpSize = 2; // 32 bit operand size - else - logOpSize = 1; // 16 bit operand size - } + if (emi.rex.w) + logOpSize = 3; // 64 bit operand size + else if (emi.legacy.op) + logOpSize = m5Reg.altOp; + else + logOpSize = m5Reg.defOp; //Set the actual op size emi.opSize = 1 << logOpSize; @@ -251,41 +232,18 @@ namespace X86ISA //Figure out the effective address size. This can be overriden to //a fixed value at the decoder level. int logAddrSize; - if(emi.mode.submode == SixtyFourBitMode) - { - if(emi.legacy.addr) - logAddrSize = 2; // 32 bit address size - else - logAddrSize = 3; // 64 bit address size - } - else if(csAttr.defaultSize) - { - if(emi.legacy.addr) - logAddrSize = 1; // 16 bit address size - else - logAddrSize = 2; // 32 bit address size - } - else // 16 bit default operand size - { - if(emi.legacy.addr) - logAddrSize = 2; // 32 bit address size - else - logAddrSize = 1; // 16 bit address size - } - - SegAttr ssAttr = tc->readMiscRegNoEffect(MISCREG_SS_ATTR); - //Figure out the effective stack width. This can be overriden to - //a fixed value at the decoder level. - if(emi.mode.submode == SixtyFourBitMode) - emi.stackSize = 8; // 64 bit stack width - else if(ssAttr.defaultSize) - emi.stackSize = 4; // 32 bit stack width + if(emi.legacy.addr) + logAddrSize = m5Reg.altAddr; else - emi.stackSize = 2; // 16 bit stack width + logAddrSize = m5Reg.defAddr; //Set the actual address size emi.addrSize = 1 << logAddrSize; + //Figure out the effective stack width. This can be overriden to + //a fixed value at the decoder level. + emi.stackSize = 1 << m5Reg.stack; + //Figure out how big of an immediate we'll retreive based //on the opcode. int immType = ImmediateType[emi.opcode.num - 1][nextByte]; @@ -318,9 +276,7 @@ namespace X86ISA ModRM modRM; modRM = nextByte; DPRINTF(Predecoder, "Found modrm byte %#x.\n", nextByte); - SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR); - if (emi.mode.submode != SixtyFourBitMode && - !csAttr.defaultSize) { + if (m5Reg.defOp == 1) { //figure out 16 bit displacement size if ((modRM.mod == 0 && modRM.rm == 6) || modRM.mod == 2) displacementSize = 2; diff --git a/src/arch/x86/predecoder.hh b/src/arch/x86/predecoder.hh index a16ce6fb8..4893f1de9 100644 --- a/src/arch/x86/predecoder.hh +++ b/src/arch/x86/predecoder.hh @@ -61,6 +61,7 @@ #include #include "arch/x86/types.hh" +#include "arch/x86/miscregs.hh" #include "base/bitfield.hh" #include "base/misc.hh" #include "base/trace.hh" @@ -91,10 +92,11 @@ namespace X86ISA int offset; //The extended machine instruction being generated ExtMachInst emi; + HandyM5Reg m5Reg; inline uint8_t getNextByte() { - return (fetchChunk >> (offset * 8)) & 0xff; + return ((uint8_t *)&fetchChunk)[offset]; } void getImmediate(int &collected, uint64_t ¤t, int size) @@ -182,6 +184,7 @@ namespace X86ISA { emi.mode.mode = LongMode; emi.mode.submode = SixtyFourBitMode; + m5Reg = 0; } void reset() diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index 43dd4a591..f7b5468b4 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -232,6 +232,15 @@ X86_64LiveProcess::startup() tc->setMiscRegNoEffect(MISCREG_CS_ATTR, csAttr); + Efer efer = 0; + efer.sce = 1; // Enable system call extensions. + efer.lme = 1; // Enable long mode. + efer.lma = 1; // Activate long mode. + efer.nxe = 1; // Enable nx support. + efer.svme = 0; // Disable svm support for now. It isn't implemented. + efer.ffxsr = 1; // Turn on fast fxsave and fxrstor. + tc->setMiscReg(MISCREG_EFER, efer); + //Set up the registers that describe the operating mode. CR0 cr0 = 0; cr0.pg = 1; // Turn on paging. @@ -248,15 +257,6 @@ X86_64LiveProcess::startup() // setting it to one. cr0.pe = 1; // We're definitely in protected mode. tc->setMiscReg(MISCREG_CR0, cr0); - - Efer efer = 0; - efer.sce = 1; // Enable system call extensions. - efer.lme = 1; // Enable long mode. - efer.lma = 1; // Activate long mode. - efer.nxe = 1; // Enable nx support. - efer.svme = 0; // Disable svm support for now. It isn't implemented. - efer.ffxsr = 1; // Turn on fast fxsave and fxrstor. - tc->setMiscReg(MISCREG_EFER, efer); } } @@ -340,6 +340,15 @@ I386LiveProcess::startup() // Set the LDT selector to 0 to deactivate it. tc->setMiscRegNoEffect(MISCREG_TSL, 0); + Efer efer = 0; + efer.sce = 1; // Enable system call extensions. + efer.lme = 1; // Enable long mode. + efer.lma = 0; // Deactivate long mode. + efer.nxe = 1; // Enable nx support. + efer.svme = 0; // Disable svm support for now. It isn't implemented. + efer.ffxsr = 1; // Turn on fast fxsave and fxrstor. + tc->setMiscReg(MISCREG_EFER, efer); + //Set up the registers that describe the operating mode. CR0 cr0 = 0; cr0.pg = 1; // Turn on paging. @@ -356,15 +365,6 @@ I386LiveProcess::startup() // setting it to one. cr0.pe = 1; // We're definitely in protected mode. tc->setMiscReg(MISCREG_CR0, cr0); - - Efer efer = 0; - efer.sce = 1; // Enable system call extensions. - efer.lme = 1; // Enable long mode. - efer.lma = 0; // Deactivate long mode. - efer.nxe = 1; // Enable nx support. - efer.svme = 0; // Disable svm support for now. It isn't implemented. - efer.ffxsr = 1; // Turn on fast fxsave and fxrstor. - tc->setMiscReg(MISCREG_EFER, efer); } } diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index f8b5c3392..1478c3e66 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -185,392 +185,394 @@ TLB::demapPage(Addr va, uint64_t asn) } } +Fault +TLB::translateInt(RequestPtr req, ThreadContext *tc) +{ + DPRINTF(TLB, "Addresses references internal memory.\n"); + Addr vaddr = req->getVaddr(); + Addr prefix = (vaddr >> 3) & IntAddrPrefixMask; + if (prefix == IntAddrPrefixCPUID) { + panic("CPUID memory space not yet implemented!\n"); + } else if (prefix == IntAddrPrefixMSR) { + vaddr = vaddr >> 3; + req->setMmapedIpr(true); + Addr regNum = 0; + switch (vaddr & ~IntAddrPrefixMask) { + case 0x10: + regNum = MISCREG_TSC; + break; + case 0x1B: + regNum = MISCREG_APIC_BASE; + break; + case 0xFE: + regNum = MISCREG_MTRRCAP; + break; + case 0x174: + regNum = MISCREG_SYSENTER_CS; + break; + case 0x175: + regNum = MISCREG_SYSENTER_ESP; + break; + case 0x176: + regNum = MISCREG_SYSENTER_EIP; + break; + case 0x179: + regNum = MISCREG_MCG_CAP; + break; + case 0x17A: + regNum = MISCREG_MCG_STATUS; + break; + case 0x17B: + regNum = MISCREG_MCG_CTL; + break; + case 0x1D9: + regNum = MISCREG_DEBUG_CTL_MSR; + break; + case 0x1DB: + regNum = MISCREG_LAST_BRANCH_FROM_IP; + break; + case 0x1DC: + regNum = MISCREG_LAST_BRANCH_TO_IP; + break; + case 0x1DD: + regNum = MISCREG_LAST_EXCEPTION_FROM_IP; + break; + case 0x1DE: + regNum = MISCREG_LAST_EXCEPTION_TO_IP; + break; + case 0x200: + regNum = MISCREG_MTRR_PHYS_BASE_0; + break; + case 0x201: + regNum = MISCREG_MTRR_PHYS_MASK_0; + break; + case 0x202: + regNum = MISCREG_MTRR_PHYS_BASE_1; + break; + case 0x203: + regNum = MISCREG_MTRR_PHYS_MASK_1; + break; + case 0x204: + regNum = MISCREG_MTRR_PHYS_BASE_2; + break; + case 0x205: + regNum = MISCREG_MTRR_PHYS_MASK_2; + break; + case 0x206: + regNum = MISCREG_MTRR_PHYS_BASE_3; + break; + case 0x207: + regNum = MISCREG_MTRR_PHYS_MASK_3; + break; + case 0x208: + regNum = MISCREG_MTRR_PHYS_BASE_4; + break; + case 0x209: + regNum = MISCREG_MTRR_PHYS_MASK_4; + break; + case 0x20A: + regNum = MISCREG_MTRR_PHYS_BASE_5; + break; + case 0x20B: + regNum = MISCREG_MTRR_PHYS_MASK_5; + break; + case 0x20C: + regNum = MISCREG_MTRR_PHYS_BASE_6; + break; + case 0x20D: + regNum = MISCREG_MTRR_PHYS_MASK_6; + break; + case 0x20E: + regNum = MISCREG_MTRR_PHYS_BASE_7; + break; + case 0x20F: + regNum = MISCREG_MTRR_PHYS_MASK_7; + break; + case 0x250: + regNum = MISCREG_MTRR_FIX_64K_00000; + break; + case 0x258: + regNum = MISCREG_MTRR_FIX_16K_80000; + break; + case 0x259: + regNum = MISCREG_MTRR_FIX_16K_A0000; + break; + case 0x268: + regNum = MISCREG_MTRR_FIX_4K_C0000; + break; + case 0x269: + regNum = MISCREG_MTRR_FIX_4K_C8000; + break; + case 0x26A: + regNum = MISCREG_MTRR_FIX_4K_D0000; + break; + case 0x26B: + regNum = MISCREG_MTRR_FIX_4K_D8000; + break; + case 0x26C: + regNum = MISCREG_MTRR_FIX_4K_E0000; + break; + case 0x26D: + regNum = MISCREG_MTRR_FIX_4K_E8000; + break; + case 0x26E: + regNum = MISCREG_MTRR_FIX_4K_F0000; + break; + case 0x26F: + regNum = MISCREG_MTRR_FIX_4K_F8000; + break; + case 0x277: + regNum = MISCREG_PAT; + break; + case 0x2FF: + regNum = MISCREG_DEF_TYPE; + break; + case 0x400: + regNum = MISCREG_MC0_CTL; + break; + case 0x404: + regNum = MISCREG_MC1_CTL; + break; + case 0x408: + regNum = MISCREG_MC2_CTL; + break; + case 0x40C: + regNum = MISCREG_MC3_CTL; + break; + case 0x410: + regNum = MISCREG_MC4_CTL; + break; + case 0x414: + regNum = MISCREG_MC5_CTL; + break; + case 0x418: + regNum = MISCREG_MC6_CTL; + break; + case 0x41C: + regNum = MISCREG_MC7_CTL; + break; + case 0x401: + regNum = MISCREG_MC0_STATUS; + break; + case 0x405: + regNum = MISCREG_MC1_STATUS; + break; + case 0x409: + regNum = MISCREG_MC2_STATUS; + break; + case 0x40D: + regNum = MISCREG_MC3_STATUS; + break; + case 0x411: + regNum = MISCREG_MC4_STATUS; + break; + case 0x415: + regNum = MISCREG_MC5_STATUS; + break; + case 0x419: + regNum = MISCREG_MC6_STATUS; + break; + case 0x41D: + regNum = MISCREG_MC7_STATUS; + break; + case 0x402: + regNum = MISCREG_MC0_ADDR; + break; + case 0x406: + regNum = MISCREG_MC1_ADDR; + break; + case 0x40A: + regNum = MISCREG_MC2_ADDR; + break; + case 0x40E: + regNum = MISCREG_MC3_ADDR; + break; + case 0x412: + regNum = MISCREG_MC4_ADDR; + break; + case 0x416: + regNum = MISCREG_MC5_ADDR; + break; + case 0x41A: + regNum = MISCREG_MC6_ADDR; + break; + case 0x41E: + regNum = MISCREG_MC7_ADDR; + break; + case 0x403: + regNum = MISCREG_MC0_MISC; + break; + case 0x407: + regNum = MISCREG_MC1_MISC; + break; + case 0x40B: + regNum = MISCREG_MC2_MISC; + break; + case 0x40F: + regNum = MISCREG_MC3_MISC; + break; + case 0x413: + regNum = MISCREG_MC4_MISC; + break; + case 0x417: + regNum = MISCREG_MC5_MISC; + break; + case 0x41B: + regNum = MISCREG_MC6_MISC; + break; + case 0x41F: + regNum = MISCREG_MC7_MISC; + break; + case 0xC0000080: + regNum = MISCREG_EFER; + break; + case 0xC0000081: + regNum = MISCREG_STAR; + break; + case 0xC0000082: + regNum = MISCREG_LSTAR; + break; + case 0xC0000083: + regNum = MISCREG_CSTAR; + break; + case 0xC0000084: + regNum = MISCREG_SF_MASK; + break; + case 0xC0000100: + regNum = MISCREG_FS_BASE; + break; + case 0xC0000101: + regNum = MISCREG_GS_BASE; + break; + case 0xC0000102: + regNum = MISCREG_KERNEL_GS_BASE; + break; + case 0xC0000103: + regNum = MISCREG_TSC_AUX; + break; + case 0xC0010000: + regNum = MISCREG_PERF_EVT_SEL0; + break; + case 0xC0010001: + regNum = MISCREG_PERF_EVT_SEL1; + break; + case 0xC0010002: + regNum = MISCREG_PERF_EVT_SEL2; + break; + case 0xC0010003: + regNum = MISCREG_PERF_EVT_SEL3; + break; + case 0xC0010004: + regNum = MISCREG_PERF_EVT_CTR0; + break; + case 0xC0010005: + regNum = MISCREG_PERF_EVT_CTR1; + break; + case 0xC0010006: + regNum = MISCREG_PERF_EVT_CTR2; + break; + case 0xC0010007: + regNum = MISCREG_PERF_EVT_CTR3; + break; + case 0xC0010010: + regNum = MISCREG_SYSCFG; + break; + case 0xC0010016: + regNum = MISCREG_IORR_BASE0; + break; + case 0xC0010017: + regNum = MISCREG_IORR_BASE1; + break; + case 0xC0010018: + regNum = MISCREG_IORR_MASK0; + break; + case 0xC0010019: + regNum = MISCREG_IORR_MASK1; + break; + case 0xC001001A: + regNum = MISCREG_TOP_MEM; + break; + case 0xC001001D: + regNum = MISCREG_TOP_MEM2; + break; + case 0xC0010114: + regNum = MISCREG_VM_CR; + break; + case 0xC0010115: + regNum = MISCREG_IGNNE; + break; + case 0xC0010116: + regNum = MISCREG_SMM_CTL; + break; + case 0xC0010117: + regNum = MISCREG_VM_HSAVE_PA; + break; + default: + return new GeneralProtection(0); + } + //The index is multiplied by the size of a MiscReg so that + //any memory dependence calculations will not see these as + //overlapping. + req->setPaddr(regNum * sizeof(MiscReg)); + return NoFault; + } else if (prefix == IntAddrPrefixIO) { + // TODO If CPL > IOPL or in virtual mode, check the I/O permission + // bitmap in the TSS. + + Addr IOPort = vaddr & ~IntAddrPrefixMask; + // Make sure the address fits in the expected 16 bit IO address + // space. + assert(!(IOPort & ~0xFFFF)); + if (IOPort == 0xCF8 && req->getSize() == 4) { + req->setMmapedIpr(true); + req->setPaddr(MISCREG_PCI_CONFIG_ADDRESS * sizeof(MiscReg)); + } else if ((IOPort & ~mask(2)) == 0xCFC) { + Addr configAddress = + tc->readMiscRegNoEffect(MISCREG_PCI_CONFIG_ADDRESS); + if (bits(configAddress, 31, 31)) { + req->setPaddr(PhysAddrPrefixPciConfig | + mbits(configAddress, 30, 2) | + (IOPort & mask(2))); + } + } else { + req->setPaddr(PhysAddrPrefixIO | IOPort); + } + return NoFault; + } else { + panic("Access to unrecognized internal address space %#x.\n", + prefix); + } +} + Fault TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation, Mode mode, bool &delayedResponse, bool timing) { + uint32_t flags = req->getFlags(); + int seg = flags & SegmentFlagMask; + bool storeCheck = flags & (StoreCheck << FlagShift); + + // If this is true, we're dealing with a request to a non-memory address + // space. + if (seg == SEGMENT_REG_MS) { + return translateInt(req, tc); + } + delayedResponse = false; Addr vaddr = req->getVaddr(); DPRINTF(TLB, "Translating vaddr %#x.\n", vaddr); - uint32_t flags = req->getFlags(); - bool storeCheck = flags & (StoreCheck << FlagShift); - int seg = flags & SegmentFlagMask; - - // If this is true, we're dealing with a request to read an internal - // value. - if (seg == SEGMENT_REG_MS) { - DPRINTF(TLB, "Addresses references internal memory.\n"); - Addr prefix = (vaddr >> 3) & IntAddrPrefixMask; - if (prefix == IntAddrPrefixCPUID) { - panic("CPUID memory space not yet implemented!\n"); - } else if (prefix == IntAddrPrefixMSR) { - vaddr = vaddr >> 3; - req->setMmapedIpr(true); - Addr regNum = 0; - switch (vaddr & ~IntAddrPrefixMask) { - case 0x10: - regNum = MISCREG_TSC; - break; - case 0x1B: - regNum = MISCREG_APIC_BASE; - break; - case 0xFE: - regNum = MISCREG_MTRRCAP; - break; - case 0x174: - regNum = MISCREG_SYSENTER_CS; - break; - case 0x175: - regNum = MISCREG_SYSENTER_ESP; - break; - case 0x176: - regNum = MISCREG_SYSENTER_EIP; - break; - case 0x179: - regNum = MISCREG_MCG_CAP; - break; - case 0x17A: - regNum = MISCREG_MCG_STATUS; - break; - case 0x17B: - regNum = MISCREG_MCG_CTL; - break; - case 0x1D9: - regNum = MISCREG_DEBUG_CTL_MSR; - break; - case 0x1DB: - regNum = MISCREG_LAST_BRANCH_FROM_IP; - break; - case 0x1DC: - regNum = MISCREG_LAST_BRANCH_TO_IP; - break; - case 0x1DD: - regNum = MISCREG_LAST_EXCEPTION_FROM_IP; - break; - case 0x1DE: - regNum = MISCREG_LAST_EXCEPTION_TO_IP; - break; - case 0x200: - regNum = MISCREG_MTRR_PHYS_BASE_0; - break; - case 0x201: - regNum = MISCREG_MTRR_PHYS_MASK_0; - break; - case 0x202: - regNum = MISCREG_MTRR_PHYS_BASE_1; - break; - case 0x203: - regNum = MISCREG_MTRR_PHYS_MASK_1; - break; - case 0x204: - regNum = MISCREG_MTRR_PHYS_BASE_2; - break; - case 0x205: - regNum = MISCREG_MTRR_PHYS_MASK_2; - break; - case 0x206: - regNum = MISCREG_MTRR_PHYS_BASE_3; - break; - case 0x207: - regNum = MISCREG_MTRR_PHYS_MASK_3; - break; - case 0x208: - regNum = MISCREG_MTRR_PHYS_BASE_4; - break; - case 0x209: - regNum = MISCREG_MTRR_PHYS_MASK_4; - break; - case 0x20A: - regNum = MISCREG_MTRR_PHYS_BASE_5; - break; - case 0x20B: - regNum = MISCREG_MTRR_PHYS_MASK_5; - break; - case 0x20C: - regNum = MISCREG_MTRR_PHYS_BASE_6; - break; - case 0x20D: - regNum = MISCREG_MTRR_PHYS_MASK_6; - break; - case 0x20E: - regNum = MISCREG_MTRR_PHYS_BASE_7; - break; - case 0x20F: - regNum = MISCREG_MTRR_PHYS_MASK_7; - break; - case 0x250: - regNum = MISCREG_MTRR_FIX_64K_00000; - break; - case 0x258: - regNum = MISCREG_MTRR_FIX_16K_80000; - break; - case 0x259: - regNum = MISCREG_MTRR_FIX_16K_A0000; - break; - case 0x268: - regNum = MISCREG_MTRR_FIX_4K_C0000; - break; - case 0x269: - regNum = MISCREG_MTRR_FIX_4K_C8000; - break; - case 0x26A: - regNum = MISCREG_MTRR_FIX_4K_D0000; - break; - case 0x26B: - regNum = MISCREG_MTRR_FIX_4K_D8000; - break; - case 0x26C: - regNum = MISCREG_MTRR_FIX_4K_E0000; - break; - case 0x26D: - regNum = MISCREG_MTRR_FIX_4K_E8000; - break; - case 0x26E: - regNum = MISCREG_MTRR_FIX_4K_F0000; - break; - case 0x26F: - regNum = MISCREG_MTRR_FIX_4K_F8000; - break; - case 0x277: - regNum = MISCREG_PAT; - break; - case 0x2FF: - regNum = MISCREG_DEF_TYPE; - break; - case 0x400: - regNum = MISCREG_MC0_CTL; - break; - case 0x404: - regNum = MISCREG_MC1_CTL; - break; - case 0x408: - regNum = MISCREG_MC2_CTL; - break; - case 0x40C: - regNum = MISCREG_MC3_CTL; - break; - case 0x410: - regNum = MISCREG_MC4_CTL; - break; - case 0x414: - regNum = MISCREG_MC5_CTL; - break; - case 0x418: - regNum = MISCREG_MC6_CTL; - break; - case 0x41C: - regNum = MISCREG_MC7_CTL; - break; - case 0x401: - regNum = MISCREG_MC0_STATUS; - break; - case 0x405: - regNum = MISCREG_MC1_STATUS; - break; - case 0x409: - regNum = MISCREG_MC2_STATUS; - break; - case 0x40D: - regNum = MISCREG_MC3_STATUS; - break; - case 0x411: - regNum = MISCREG_MC4_STATUS; - break; - case 0x415: - regNum = MISCREG_MC5_STATUS; - break; - case 0x419: - regNum = MISCREG_MC6_STATUS; - break; - case 0x41D: - regNum = MISCREG_MC7_STATUS; - break; - case 0x402: - regNum = MISCREG_MC0_ADDR; - break; - case 0x406: - regNum = MISCREG_MC1_ADDR; - break; - case 0x40A: - regNum = MISCREG_MC2_ADDR; - break; - case 0x40E: - regNum = MISCREG_MC3_ADDR; - break; - case 0x412: - regNum = MISCREG_MC4_ADDR; - break; - case 0x416: - regNum = MISCREG_MC5_ADDR; - break; - case 0x41A: - regNum = MISCREG_MC6_ADDR; - break; - case 0x41E: - regNum = MISCREG_MC7_ADDR; - break; - case 0x403: - regNum = MISCREG_MC0_MISC; - break; - case 0x407: - regNum = MISCREG_MC1_MISC; - break; - case 0x40B: - regNum = MISCREG_MC2_MISC; - break; - case 0x40F: - regNum = MISCREG_MC3_MISC; - break; - case 0x413: - regNum = MISCREG_MC4_MISC; - break; - case 0x417: - regNum = MISCREG_MC5_MISC; - break; - case 0x41B: - regNum = MISCREG_MC6_MISC; - break; - case 0x41F: - regNum = MISCREG_MC7_MISC; - break; - case 0xC0000080: - regNum = MISCREG_EFER; - break; - case 0xC0000081: - regNum = MISCREG_STAR; - break; - case 0xC0000082: - regNum = MISCREG_LSTAR; - break; - case 0xC0000083: - regNum = MISCREG_CSTAR; - break; - case 0xC0000084: - regNum = MISCREG_SF_MASK; - break; - case 0xC0000100: - regNum = MISCREG_FS_BASE; - break; - case 0xC0000101: - regNum = MISCREG_GS_BASE; - break; - case 0xC0000102: - regNum = MISCREG_KERNEL_GS_BASE; - break; - case 0xC0000103: - regNum = MISCREG_TSC_AUX; - break; - case 0xC0010000: - regNum = MISCREG_PERF_EVT_SEL0; - break; - case 0xC0010001: - regNum = MISCREG_PERF_EVT_SEL1; - break; - case 0xC0010002: - regNum = MISCREG_PERF_EVT_SEL2; - break; - case 0xC0010003: - regNum = MISCREG_PERF_EVT_SEL3; - break; - case 0xC0010004: - regNum = MISCREG_PERF_EVT_CTR0; - break; - case 0xC0010005: - regNum = MISCREG_PERF_EVT_CTR1; - break; - case 0xC0010006: - regNum = MISCREG_PERF_EVT_CTR2; - break; - case 0xC0010007: - regNum = MISCREG_PERF_EVT_CTR3; - break; - case 0xC0010010: - regNum = MISCREG_SYSCFG; - break; - case 0xC0010016: - regNum = MISCREG_IORR_BASE0; - break; - case 0xC0010017: - regNum = MISCREG_IORR_BASE1; - break; - case 0xC0010018: - regNum = MISCREG_IORR_MASK0; - break; - case 0xC0010019: - regNum = MISCREG_IORR_MASK1; - break; - case 0xC001001A: - regNum = MISCREG_TOP_MEM; - break; - case 0xC001001D: - regNum = MISCREG_TOP_MEM2; - break; - case 0xC0010114: - regNum = MISCREG_VM_CR; - break; - case 0xC0010115: - regNum = MISCREG_IGNNE; - break; - case 0xC0010116: - regNum = MISCREG_SMM_CTL; - break; - case 0xC0010117: - regNum = MISCREG_VM_HSAVE_PA; - break; - default: - return new GeneralProtection(0); - } - //The index is multiplied by the size of a MiscReg so that - //any memory dependence calculations will not see these as - //overlapping. - req->setPaddr(regNum * sizeof(MiscReg)); - return NoFault; - } else if (prefix == IntAddrPrefixIO) { - // TODO If CPL > IOPL or in virtual mode, check the I/O permission - // bitmap in the TSS. - - Addr IOPort = vaddr & ~IntAddrPrefixMask; - // Make sure the address fits in the expected 16 bit IO address - // space. - assert(!(IOPort & ~0xFFFF)); - if (IOPort == 0xCF8 && req->getSize() == 4) { - req->setMmapedIpr(true); - req->setPaddr(MISCREG_PCI_CONFIG_ADDRESS * sizeof(MiscReg)); - } else if ((IOPort & ~mask(2)) == 0xCFC) { - Addr configAddress = - tc->readMiscRegNoEffect(MISCREG_PCI_CONFIG_ADDRESS); - if (bits(configAddress, 31, 31)) { - req->setPaddr(PhysAddrPrefixPciConfig | - mbits(configAddress, 30, 2) | - (IOPort & mask(2))); - } - } else { - req->setPaddr(PhysAddrPrefixIO | IOPort); - } - return NoFault; - } else { - panic("Access to unrecognized internal address space %#x.\n", - prefix); - } - } - - // Get cr0. This will tell us how to do translation. We'll assume it was - // verified to be correct and consistent when set. - CR0 cr0 = tc->readMiscRegNoEffect(MISCREG_CR0); + HandyM5Reg m5Reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); // If protected mode has been enabled... - if (cr0.pe) { + if (m5Reg.prot) { DPRINTF(TLB, "In protected mode.\n"); - Efer efer = tc->readMiscRegNoEffect(MISCREG_EFER); - SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR); // If we're not in 64-bit mode, do protection/limit checks - if (!efer.lma || !csAttr.longMode) { + if (m5Reg.mode != LongMode) { DPRINTF(TLB, "Not in long mode. Checking segment protection.\n"); // Check for a NULL segment selector. if (!(seg == SEGMENT_REG_TSG || seg == SYS_SEGMENT_REG_IDTR || - seg == SEGMENT_REG_HS || seg == SEGMENT_REG_LS || - seg == SEGMENT_REG_MS) + seg == SEGMENT_REG_HS || seg == SEGMENT_REG_LS) && !tc->readMiscRegNoEffect(MISCREG_SEG_SEL(seg))) return new GeneralProtection(0); bool expandDown = false; @@ -589,6 +591,7 @@ TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation, // address size is 64 bits, overridable to 32. int size = 32; bool sizeOverride = (flags & (AddrSizeFlagBit << FlagShift)); + SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR); if ((csAttr.defaultSize && sizeOverride) || (!csAttr.defaultSize && !sizeOverride)) size = 16; @@ -605,7 +608,7 @@ TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation, } } // If paging is enabled, do the translation. - if (cr0.pg) { + if (m5Reg.paging) { DPRINTF(TLB, "Paging enabled.\n"); // The vaddr already has the segment base applied. TlbEntry *entry = lookup(vaddr); @@ -643,7 +646,7 @@ TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation, #endif } // Do paging protection checks. - bool inUser = (csAttr.dpl == 3 && + bool inUser = (m5Reg.cpl == 3 && !(flags & (CPL0FlagBit << FlagShift))); if ((inUser && !entry->user) || (mode == Write && !entry->writable)) { diff --git a/src/arch/x86/tlb.hh b/src/arch/x86/tlb.hh index f55c26435..dca95eaaf 100644 --- a/src/arch/x86/tlb.hh +++ b/src/arch/x86/tlb.hh @@ -124,6 +124,8 @@ namespace X86ISA EntryList freeList; EntryList entryList; + Fault translateInt(RequestPtr req, ThreadContext *tc); + Fault translate(RequestPtr req, ThreadContext *tc, Translation *translation, Mode mode, bool &delayedResponse, bool timing); diff --git a/src/sim/SConscript b/src/sim/SConscript index 750007947..c13ea9909 100644 --- a/src/sim/SConscript +++ b/src/sim/SConscript @@ -41,7 +41,7 @@ Source('debug.cc') Source('eventq.cc') Source('faults.cc') Source('init.cc') -BinSource('main.cc') +Source('main.cc', bin_only=True) Source('pseudo_inst.cc') Source('root.cc') Source('serialize.cc')