merge code
This commit is contained in:
commit
db79945ad0
12 changed files with 707 additions and 663 deletions
|
@ -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
|
||||
|
|
363
src/SConscript
363
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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
#include <cassert>
|
||||
|
||||
#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()
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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')
|
||||
|
|
Loading…
Reference in a new issue