Merge ktlim@zizzer:/bk/newmem
into zamp.eecs.umich.edu:/z/ktlim2/clean/o3-merge/newmem --HG-- extra : convert_revision : 0c2db1e1b5fdb91c1ac5705ab872a6bfb575a67a
This commit is contained in:
commit
b5e68fb546
294 changed files with 8976 additions and 5427 deletions
55
SConstruct
55
SConstruct
|
@ -270,6 +270,12 @@ if not conf.CheckLib(py_version_name):
|
||||||
print "Error: can't find Python library", py_version_name
|
print "Error: can't find Python library", py_version_name
|
||||||
Exit(1)
|
Exit(1)
|
||||||
|
|
||||||
|
# On Solaris you need to use libsocket for socket ops
|
||||||
|
if not conf.CheckLibWithHeader(None, 'sys/socket.h', 'C++', 'accept(0,0,0);'):
|
||||||
|
if not conf.CheckLibWithHeader('socket', 'sys/socket.h', 'C++', 'accept(0,0,0);'):
|
||||||
|
print "Can't find library with socket calls (e.g. accept())"
|
||||||
|
Exit(1)
|
||||||
|
|
||||||
# Check for zlib. If the check passes, libz will be automatically
|
# Check for zlib. If the check passes, libz will be automatically
|
||||||
# added to the LIBS environment variable.
|
# added to the LIBS environment variable.
|
||||||
if not conf.CheckLibWithHeader('z', 'zlib.h', 'C++'):
|
if not conf.CheckLibWithHeader('z', 'zlib.h', 'C++'):
|
||||||
|
@ -314,8 +320,10 @@ env['ALL_ISA_LIST'] = ['alpha', 'sparc', 'mips']
|
||||||
|
|
||||||
# Define the universe of supported CPU models
|
# Define the universe of supported CPU models
|
||||||
env['ALL_CPU_LIST'] = ['AtomicSimpleCPU', 'TimingSimpleCPU',
|
env['ALL_CPU_LIST'] = ['AtomicSimpleCPU', 'TimingSimpleCPU',
|
||||||
'FullCPU', 'O3CPU',
|
'O3CPU', 'OzoneCPU']
|
||||||
'OzoneCPU']
|
|
||||||
|
if os.path.isdir(os.path.join(SRCDIR, 'src/encumbered/cpu/full')):
|
||||||
|
env['ALL_CPU_LIST'] += ['FullCPU']
|
||||||
|
|
||||||
# Sticky options get saved in the options file so they persist from
|
# Sticky options get saved in the options file so they persist from
|
||||||
# one invocation to the next (unless overridden, in which case the new
|
# one invocation to the next (unless overridden, in which case the new
|
||||||
|
@ -362,7 +370,7 @@ nonsticky_opts.AddOptions(
|
||||||
# These options get exported to #defines in config/*.hh (see src/SConscript).
|
# These options get exported to #defines in config/*.hh (see src/SConscript).
|
||||||
env.ExportOptions = ['FULL_SYSTEM', 'ALPHA_TLASER', 'USE_FENV', \
|
env.ExportOptions = ['FULL_SYSTEM', 'ALPHA_TLASER', 'USE_FENV', \
|
||||||
'USE_MYSQL', 'NO_FAST_ALLOC', 'SS_COMPATIBLE_FP', \
|
'USE_MYSQL', 'NO_FAST_ALLOC', 'SS_COMPATIBLE_FP', \
|
||||||
'USE_CHECKER', 'PYTHONHOME']
|
'USE_CHECKER', 'PYTHONHOME', 'TARGET_ISA']
|
||||||
|
|
||||||
# Define a handy 'no-op' action
|
# Define a handy 'no-op' action
|
||||||
def no_action(target, source, env):
|
def no_action(target, source, env):
|
||||||
|
@ -453,6 +461,46 @@ env.SConscript('ext/libelf/SConscript',
|
||||||
build_dir = os.path.join(build_root, 'libelf'),
|
build_dir = os.path.join(build_root, 'libelf'),
|
||||||
exports = 'env')
|
exports = 'env')
|
||||||
|
|
||||||
|
###################################################
|
||||||
|
#
|
||||||
|
# This function is used to set up a directory with switching headers
|
||||||
|
#
|
||||||
|
###################################################
|
||||||
|
|
||||||
|
def make_switching_dir(dirname, switch_headers, env):
|
||||||
|
# Generate the header. target[0] is the full path of the output
|
||||||
|
# header to generate. 'source' is a dummy variable, since we get the
|
||||||
|
# list of ISAs from env['ALL_ISA_LIST'].
|
||||||
|
def gen_switch_hdr(target, source, env):
|
||||||
|
fname = str(target[0])
|
||||||
|
basename = os.path.basename(fname)
|
||||||
|
f = open(fname, 'w')
|
||||||
|
f.write('#include "arch/isa_specific.hh"\n')
|
||||||
|
cond = '#if'
|
||||||
|
for isa in env['ALL_ISA_LIST']:
|
||||||
|
f.write('%s THE_ISA == %s_ISA\n#include "%s/%s/%s"\n'
|
||||||
|
% (cond, isa.upper(), dirname, isa, basename))
|
||||||
|
cond = '#elif'
|
||||||
|
f.write('#else\n#error "THE_ISA not set"\n#endif\n')
|
||||||
|
f.close()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# String to print when generating header
|
||||||
|
def gen_switch_hdr_string(target, source, env):
|
||||||
|
return "Generating switch header " + str(target[0])
|
||||||
|
|
||||||
|
# Build SCons Action object. 'varlist' specifies env vars that this
|
||||||
|
# action depends on; when env['ALL_ISA_LIST'] changes these actions
|
||||||
|
# should get re-executed.
|
||||||
|
switch_hdr_action = Action(gen_switch_hdr, gen_switch_hdr_string,
|
||||||
|
varlist=['ALL_ISA_LIST'])
|
||||||
|
|
||||||
|
# Instantiate actions for each header
|
||||||
|
for hdr in switch_headers:
|
||||||
|
env.Command(hdr, [], switch_hdr_action)
|
||||||
|
|
||||||
|
env.make_switching_dir = make_switching_dir
|
||||||
|
|
||||||
###################################################
|
###################################################
|
||||||
#
|
#
|
||||||
# Define build environments for selected configurations.
|
# Define build environments for selected configurations.
|
||||||
|
@ -560,6 +608,7 @@ for build_path in build_paths:
|
||||||
|
|
||||||
Help(help_text)
|
Help(help_text)
|
||||||
|
|
||||||
|
|
||||||
###################################################
|
###################################################
|
||||||
#
|
#
|
||||||
# Let SCons do its thing. At this point SCons will use the defined
|
# Let SCons do its thing. At this point SCons will use the defined
|
||||||
|
|
|
@ -78,6 +78,27 @@ def makeLinuxAlphaSystem(mem_mode, mdesc = None):
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def makeSparcSystem(mem_mode, mdesc = None):
|
||||||
|
self = SparcSystem()
|
||||||
|
if not mdesc:
|
||||||
|
# generic system
|
||||||
|
mdesc = SysConfig()
|
||||||
|
self.readfile = mdesc.script()
|
||||||
|
self.membus = Bus(bus_id=1)
|
||||||
|
self.physmem = PhysicalMemory(range = AddrRange(mdesc.mem()))
|
||||||
|
self.physmem.port = self.membus.port
|
||||||
|
self.rom.port = self.membus.port
|
||||||
|
self.intrctrl = IntrControl()
|
||||||
|
self.mem_mode = mem_mode
|
||||||
|
self.kernel = binary('vmlinux')
|
||||||
|
|
||||||
|
self.reset_bin = binary('reset.bin')
|
||||||
|
self.hypervisor_bin = binary('q.bin')
|
||||||
|
self.openboot_bin = binary('openboot.bin')
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
|
||||||
def makeDualRoot(testSystem, driveSystem, dumpfile):
|
def makeDualRoot(testSystem, driveSystem, dumpfile):
|
||||||
self = Root()
|
self = Root()
|
||||||
self.testsys = testSystem
|
self.testsys = testSystem
|
||||||
|
|
|
@ -27,12 +27,37 @@
|
||||||
# Authors: Lisa Hsu
|
# Authors: Lisa Hsu
|
||||||
|
|
||||||
from os import getcwd
|
from os import getcwd
|
||||||
|
from os.path import join as joinpath
|
||||||
import m5
|
import m5
|
||||||
from m5.objects import *
|
from m5.objects import *
|
||||||
m5.AddToPath('../common')
|
m5.AddToPath('../common')
|
||||||
from Caches import L1Cache
|
from Caches import L1Cache
|
||||||
|
|
||||||
def run(options, root, testsys):
|
def setCPUClass(options):
|
||||||
|
|
||||||
|
atomic = False
|
||||||
|
if options.timing:
|
||||||
|
TmpClass = TimingSimpleCPU
|
||||||
|
elif options.detailed:
|
||||||
|
TmpClass = DerivO3CPU
|
||||||
|
else:
|
||||||
|
TmpClass = AtomicSimpleCPU
|
||||||
|
atomic = True
|
||||||
|
|
||||||
|
CPUClass = None
|
||||||
|
test_mem_mode = 'atomic'
|
||||||
|
|
||||||
|
if not atomic:
|
||||||
|
if options.checkpoint_restore:
|
||||||
|
CPUClass = TmpClass
|
||||||
|
TmpClass = AtomicSimpleCPU
|
||||||
|
else:
|
||||||
|
test_mem_mode = 'timing'
|
||||||
|
|
||||||
|
return (TmpClass, test_mem_mode, CPUClass)
|
||||||
|
|
||||||
|
|
||||||
|
def run(options, root, testsys, cpu_class):
|
||||||
if options.maxtick:
|
if options.maxtick:
|
||||||
maxtick = options.maxtick
|
maxtick = options.maxtick
|
||||||
elif options.maxtime:
|
elif options.maxtime:
|
||||||
|
@ -40,7 +65,7 @@ def run(options, root, testsys):
|
||||||
print "simulating for: ", simtime
|
print "simulating for: ", simtime
|
||||||
maxtick = simtime
|
maxtick = simtime
|
||||||
else:
|
else:
|
||||||
maxtick = -1
|
maxtick = m5.MaxTick
|
||||||
|
|
||||||
if options.checkpoint_dir:
|
if options.checkpoint_dir:
|
||||||
cptdir = options.checkpoint_dir
|
cptdir = options.checkpoint_dir
|
||||||
|
@ -49,31 +74,55 @@ def run(options, root, testsys):
|
||||||
|
|
||||||
np = options.num_cpus
|
np = options.num_cpus
|
||||||
max_checkpoints = options.max_checkpoints
|
max_checkpoints = options.max_checkpoints
|
||||||
|
switch_cpus = None
|
||||||
|
|
||||||
|
if cpu_class:
|
||||||
|
switch_cpus = [cpu_class(defer_registration=True, cpu_id=(np+i))
|
||||||
|
for i in xrange(np)]
|
||||||
|
|
||||||
|
for i in xrange(np):
|
||||||
|
switch_cpus[i].system = testsys
|
||||||
|
if not m5.build_env['FULL_SYSTEM']:
|
||||||
|
switch_cpus[i].workload = testsys.cpu[i].workload
|
||||||
|
switch_cpus[i].clock = testsys.cpu[0].clock
|
||||||
|
if options.caches:
|
||||||
|
switch_cpus[i].addPrivateSplitL1Caches(L1Cache(size = '32kB'),
|
||||||
|
L1Cache(size = '64kB'))
|
||||||
|
switch_cpus[i].connectMemPorts(testsys.membus)
|
||||||
|
|
||||||
|
root.switch_cpus = switch_cpus
|
||||||
|
switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)]
|
||||||
|
|
||||||
if options.standard_switch:
|
if options.standard_switch:
|
||||||
switch_cpus = [TimingSimpleCPU(defer_registration=True, cpu_id=(np+i))
|
switch_cpus = [TimingSimpleCPU(defer_registration=True, cpu_id=(np+i))
|
||||||
for i in xrange(np)]
|
for i in xrange(np)]
|
||||||
switch_cpus1 = [DerivO3CPU(defer_registration=True, cpu_id=(2*np+i))
|
switch_cpus_1 = [DerivO3CPU(defer_registration=True, cpu_id=(2*np+i))
|
||||||
for i in xrange(np)]
|
for i in xrange(np)]
|
||||||
|
|
||||||
for i in xrange(np):
|
for i in xrange(np):
|
||||||
switch_cpus[i].system = testsys
|
switch_cpus[i].system = testsys
|
||||||
switch_cpus1[i].system = testsys
|
switch_cpus_1[i].system = testsys
|
||||||
if not m5.build_env['FULL_SYSTEM']:
|
if not m5.build_env['FULL_SYSTEM']:
|
||||||
switch_cpus[i].workload = testsys.cpu[i].workload
|
switch_cpus[i].workload = testsys.cpu[i].workload
|
||||||
switch_cpus1[i].workload = testsys.cpu[i].workload
|
switch_cpus_1[i].workload = testsys.cpu[i].workload
|
||||||
switch_cpus[i].clock = testsys.cpu[0].clock
|
switch_cpus[i].clock = testsys.cpu[0].clock
|
||||||
switch_cpus1[i].clock = testsys.cpu[0].clock
|
switch_cpus_1[i].clock = testsys.cpu[0].clock
|
||||||
|
|
||||||
if options.caches:
|
if options.caches:
|
||||||
switch_cpus[i].addPrivateSplitL1Caches(L1Cache(size = '32kB'),
|
switch_cpus[i].addPrivateSplitL1Caches(L1Cache(size = '32kB'),
|
||||||
L1Cache(size = '64kB'))
|
L1Cache(size = '64kB'))
|
||||||
|
switch_cpus[i].connectMemPorts(testsys.membus)
|
||||||
|
else:
|
||||||
|
# O3 CPU must have a cache to work.
|
||||||
|
switch_cpus_1[i].addPrivateSplitL1Caches(L1Cache(size = '32kB'),
|
||||||
|
L1Cache(size = '64kB'))
|
||||||
|
switch_cpus_1[i].connectMemPorts(testsys.membus)
|
||||||
|
|
||||||
|
|
||||||
switch_cpus[i].mem = testsys.physmem
|
|
||||||
switch_cpus1[i].mem = testsys.physmem
|
|
||||||
switch_cpus[i].connectMemPorts(testsys.membus)
|
|
||||||
root.switch_cpus = switch_cpus
|
root.switch_cpus = switch_cpus
|
||||||
root.switch_cpus1 = switch_cpus1
|
root.switch_cpus_1 = switch_cpus_1
|
||||||
switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)]
|
switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)]
|
||||||
switch_cpu_list1 = [(switch_cpus[i], switch_cpus1[i]) for i in xrange(np)]
|
switch_cpu_list1 = [(switch_cpus[i], switch_cpus_1[i]) for i in xrange(np)]
|
||||||
|
|
||||||
m5.instantiate(root)
|
m5.instantiate(root)
|
||||||
|
|
||||||
|
@ -101,9 +150,9 @@ def run(options, root, testsys):
|
||||||
m5.panic('Checkpoint %d not found' % cpt_num)
|
m5.panic('Checkpoint %d not found' % cpt_num)
|
||||||
|
|
||||||
m5.restoreCheckpoint(root,
|
m5.restoreCheckpoint(root,
|
||||||
"/".join([cptdir, "cpt.%s" % cpts[cpt_num - 1]]))
|
joinpath(cptdir, "cpt.%s" % cpts[cpt_num - 1]))
|
||||||
|
|
||||||
if options.standard_switch:
|
if options.standard_switch or cpu_class:
|
||||||
exit_event = m5.simulate(10000)
|
exit_event = m5.simulate(10000)
|
||||||
|
|
||||||
## when you change to Timing (or Atomic), you halt the system given
|
## when you change to Timing (or Atomic), you halt the system given
|
||||||
|
@ -116,8 +165,9 @@ def run(options, root, testsys):
|
||||||
m5.switchCpus(switch_cpu_list)
|
m5.switchCpus(switch_cpu_list)
|
||||||
m5.resume(testsys)
|
m5.resume(testsys)
|
||||||
|
|
||||||
exit_event = m5.simulate(options.warmup)
|
if options.standard_switch:
|
||||||
m5.switchCpus(switch_cpu_list1)
|
exit_event = m5.simulate(options.warmup)
|
||||||
|
m5.switchCpus(switch_cpu_list1)
|
||||||
|
|
||||||
num_checkpoints = 0
|
num_checkpoints = 0
|
||||||
exit_cause = ''
|
exit_cause = ''
|
||||||
|
@ -135,13 +185,13 @@ def run(options, root, testsys):
|
||||||
exit_event = m5.simulate(when - m5.curTick())
|
exit_event = m5.simulate(when - m5.curTick())
|
||||||
|
|
||||||
if exit_event.getCause() == "simulate() limit reached":
|
if exit_event.getCause() == "simulate() limit reached":
|
||||||
m5.checkpoint(root, "/".join([cptdir,"cpt.%d"]))
|
m5.checkpoint(root, joinpath(cptdir, "cpt.%d"))
|
||||||
num_checkpoints += 1
|
num_checkpoints += 1
|
||||||
|
|
||||||
sim_ticks = when
|
sim_ticks = when
|
||||||
exit_cause = "maximum %d checkpoints dropped" % max_checkpoints
|
exit_cause = "maximum %d checkpoints dropped" % max_checkpoints
|
||||||
while num_checkpoints < max_checkpoints:
|
while num_checkpoints < max_checkpoints:
|
||||||
if (sim_ticks + period) > maxtick and maxtick != -1:
|
if (sim_ticks + period) > maxtick:
|
||||||
exit_event = m5.simulate(maxtick - sim_ticks)
|
exit_event = m5.simulate(maxtick - sim_ticks)
|
||||||
exit_cause = exit_event.getCause()
|
exit_cause = exit_event.getCause()
|
||||||
break
|
break
|
||||||
|
@ -151,24 +201,20 @@ def run(options, root, testsys):
|
||||||
while exit_event.getCause() == "checkpoint":
|
while exit_event.getCause() == "checkpoint":
|
||||||
exit_event = m5.simulate(sim_ticks - m5.curTick())
|
exit_event = m5.simulate(sim_ticks - m5.curTick())
|
||||||
if exit_event.getCause() == "simulate() limit reached":
|
if exit_event.getCause() == "simulate() limit reached":
|
||||||
m5.checkpoint(root, "/".join([cptdir,"cpt.%d"]))
|
m5.checkpoint(root, joinpath(cptdir, "cpt.%d"))
|
||||||
num_checkpoints += 1
|
num_checkpoints += 1
|
||||||
|
|
||||||
else: #no checkpoints being taken via this script
|
else: #no checkpoints being taken via this script
|
||||||
exit_event = m5.simulate(maxtick)
|
exit_event = m5.simulate(maxtick)
|
||||||
|
|
||||||
while exit_event.getCause() == "checkpoint":
|
while exit_event.getCause() == "checkpoint":
|
||||||
m5.checkpoint(root, "/".join([cptdir,"cpt.%d"]))
|
m5.checkpoint(root, joinpath(cptdir, "cpt.%d"))
|
||||||
num_checkpoints += 1
|
num_checkpoints += 1
|
||||||
if num_checkpoints == max_checkpoints:
|
if num_checkpoints == max_checkpoints:
|
||||||
exit_cause = "maximum %d checkpoints dropped" % max_checkpoints
|
exit_cause = "maximum %d checkpoints dropped" % max_checkpoints
|
||||||
break
|
break
|
||||||
|
|
||||||
if maxtick == -1:
|
exit_event = m5.simulate(maxtick - m5.curTick())
|
||||||
exit_event = m5.simulate(maxtick)
|
|
||||||
else:
|
|
||||||
exit_event = m5.simulate(maxtick - m5.curTick())
|
|
||||||
|
|
||||||
exit_cause = exit_event.getCause()
|
exit_cause = exit_event.getCause()
|
||||||
|
|
||||||
if exit_cause == '':
|
if exit_cause == '':
|
||||||
|
|
|
@ -30,6 +30,9 @@ import os, sys
|
||||||
from os.path import isdir, join as joinpath
|
from os.path import isdir, join as joinpath
|
||||||
from os import environ as env
|
from os import environ as env
|
||||||
|
|
||||||
|
config_path = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
config_root = os.path.dirname(config_path)
|
||||||
|
|
||||||
def disk(file):
|
def disk(file):
|
||||||
system()
|
system()
|
||||||
return joinpath(disk.dir, file)
|
return joinpath(disk.dir, file)
|
||||||
|
@ -60,7 +63,7 @@ def system():
|
||||||
if not disk.dir:
|
if not disk.dir:
|
||||||
disk.dir = joinpath(system.dir, 'disks')
|
disk.dir = joinpath(system.dir, 'disks')
|
||||||
if not script.dir:
|
if not script.dir:
|
||||||
script.dir = joinpath(system.dir, 'boot')
|
script.dir = joinpath(config_root, 'boot')
|
||||||
|
|
||||||
system.dir = None
|
system.dir = None
|
||||||
binary.dir = None
|
binary.dir = None
|
||||||
|
|
|
@ -72,16 +72,8 @@ if args:
|
||||||
DriveCPUClass = AtomicSimpleCPU
|
DriveCPUClass = AtomicSimpleCPU
|
||||||
drive_mem_mode = 'atomic'
|
drive_mem_mode = 'atomic'
|
||||||
|
|
||||||
# system under test can be any of these CPUs
|
# system under test can be any CPU
|
||||||
if options.detailed:
|
(TestCPUClass, test_mem_mode, FutureClass) = Simulation.setCPUClass(options)
|
||||||
TestCPUClass = DerivO3CPU
|
|
||||||
test_mem_mode = 'timing'
|
|
||||||
elif options.timing:
|
|
||||||
TestCPUClass = TimingSimpleCPU
|
|
||||||
test_mem_mode = 'timing'
|
|
||||||
else:
|
|
||||||
TestCPUClass = AtomicSimpleCPU
|
|
||||||
test_mem_mode = 'atomic'
|
|
||||||
|
|
||||||
TestCPUClass.clock = '2GHz'
|
TestCPUClass.clock = '2GHz'
|
||||||
DriveCPUClass.clock = '2GHz'
|
DriveCPUClass.clock = '2GHz'
|
||||||
|
@ -103,17 +95,15 @@ test_sys = makeLinuxAlphaSystem(test_mem_mode, bm[0])
|
||||||
np = options.num_cpus
|
np = options.num_cpus
|
||||||
test_sys.cpu = [TestCPUClass(cpu_id=i) for i in xrange(np)]
|
test_sys.cpu = [TestCPUClass(cpu_id=i) for i in xrange(np)]
|
||||||
for i in xrange(np):
|
for i in xrange(np):
|
||||||
if options.caches and not options.standard_switch:
|
if options.caches and not options.standard_switch and not FutureClass:
|
||||||
test_sys.cpu[i].addPrivateSplitL1Caches(L1Cache(size = '32kB'),
|
test_sys.cpu[i].addPrivateSplitL1Caches(L1Cache(size = '32kB'),
|
||||||
L1Cache(size = '64kB'))
|
L1Cache(size = '64kB'))
|
||||||
test_sys.cpu[i].connectMemPorts(test_sys.membus)
|
test_sys.cpu[i].connectMemPorts(test_sys.membus)
|
||||||
test_sys.cpu[i].mem = test_sys.physmem
|
|
||||||
|
|
||||||
if len(bm) == 2:
|
if len(bm) == 2:
|
||||||
drive_sys = makeLinuxAlphaSystem(drive_mem_mode, bm[1])
|
drive_sys = makeLinuxAlphaSystem(drive_mem_mode, bm[1])
|
||||||
drive_sys.cpu = DriveCPUClass(cpu_id=0)
|
drive_sys.cpu = DriveCPUClass(cpu_id=0)
|
||||||
drive_sys.cpu.connectMemPorts(drive_sys.membus)
|
drive_sys.cpu.connectMemPorts(drive_sys.membus)
|
||||||
drive_sys.cpu.mem = drive_sys.physmem
|
|
||||||
root = makeDualRoot(test_sys, drive_sys, options.etherdump)
|
root = makeDualRoot(test_sys, drive_sys, options.etherdump)
|
||||||
elif len(bm) == 1:
|
elif len(bm) == 1:
|
||||||
root = Root(clock = '1THz', system = test_sys)
|
root = Root(clock = '1THz', system = test_sys)
|
||||||
|
@ -121,4 +111,4 @@ else:
|
||||||
print "Error I don't know how to create more than 2 systems."
|
print "Error I don't know how to create more than 2 systems."
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
Simulation.run(options, root, test_sys)
|
Simulation.run(options, root, test_sys, FutureClass)
|
||||||
|
|
|
@ -41,10 +41,6 @@ from Caches import *
|
||||||
config_path = os.path.dirname(os.path.abspath(__file__))
|
config_path = os.path.dirname(os.path.abspath(__file__))
|
||||||
config_root = os.path.dirname(config_path)
|
config_root = os.path.dirname(config_path)
|
||||||
m5_root = os.path.dirname(config_root)
|
m5_root = os.path.dirname(config_root)
|
||||||
print m5_root
|
|
||||||
print config_path
|
|
||||||
print config_root
|
|
||||||
|
|
||||||
|
|
||||||
parser = optparse.OptionParser()
|
parser = optparse.OptionParser()
|
||||||
|
|
||||||
|
@ -92,16 +88,7 @@ if options.detailed:
|
||||||
process += [smt_process, ]
|
process += [smt_process, ]
|
||||||
smt_idx += 1
|
smt_idx += 1
|
||||||
|
|
||||||
|
(CPUClass, test_mem_mode, FutureClass) = Simulation.setCPUClass(options)
|
||||||
if options.timing:
|
|
||||||
CPUClass = TimingSimpleCPU
|
|
||||||
test_mem_mode = 'timing'
|
|
||||||
elif options.detailed:
|
|
||||||
CPUClass = DerivO3CPU
|
|
||||||
test_mem_mode = 'timing'
|
|
||||||
else:
|
|
||||||
CPUClass = AtomicSimpleCPU
|
|
||||||
test_mem_mode = 'atomic'
|
|
||||||
|
|
||||||
CPUClass.clock = '2GHz'
|
CPUClass.clock = '2GHz'
|
||||||
|
|
||||||
|
@ -114,13 +101,12 @@ system = System(cpu = [CPUClass(cpu_id=i) for i in xrange(np)],
|
||||||
system.physmem.port = system.membus.port
|
system.physmem.port = system.membus.port
|
||||||
|
|
||||||
for i in xrange(np):
|
for i in xrange(np):
|
||||||
if options.caches and not options.standard_switch:
|
if options.caches and not options.standard_switch and not FutureClass:
|
||||||
system.cpu[i].addPrivateSplitL1Caches(L1Cache(size = '32kB'),
|
system.cpu[i].addPrivateSplitL1Caches(L1Cache(size = '32kB'),
|
||||||
L1Cache(size = '64kB'))
|
L1Cache(size = '64kB'))
|
||||||
system.cpu[i].connectMemPorts(system.membus)
|
system.cpu[i].connectMemPorts(system.membus)
|
||||||
system.cpu[i].mem = system.physmem
|
|
||||||
system.cpu[i].workload = process
|
system.cpu[i].workload = process
|
||||||
|
|
||||||
root = Root(system = system)
|
root = Root(system = system)
|
||||||
|
|
||||||
Simulation.run(options, root, system)
|
Simulation.run(options, root, system, FutureClass)
|
||||||
|
|
137
src/SConscript
137
src/SConscript
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from os.path import isdir
|
from os.path import isfile, join as joinpath
|
||||||
|
|
||||||
# This file defines how to build a particular configuration of M5
|
# This file defines how to build a particular configuration of M5
|
||||||
# based on variable settings in the 'env' build environment.
|
# based on variable settings in the 'env' build environment.
|
||||||
|
@ -74,6 +74,7 @@ base_sources = Split('''
|
||||||
base/loader/aout_object.cc
|
base/loader/aout_object.cc
|
||||||
base/loader/ecoff_object.cc
|
base/loader/ecoff_object.cc
|
||||||
base/loader/elf_object.cc
|
base/loader/elf_object.cc
|
||||||
|
base/loader/raw_object.cc
|
||||||
base/loader/object_file.cc
|
base/loader/object_file.cc
|
||||||
base/loader/symtab.cc
|
base/loader/symtab.cc
|
||||||
base/stats/events.cc
|
base/stats/events.cc
|
||||||
|
@ -146,45 +147,6 @@ base_sources = Split('''
|
||||||
sim/trace_context.cc
|
sim/trace_context.cc
|
||||||
''')
|
''')
|
||||||
|
|
||||||
# Old FullCPU sources
|
|
||||||
full_cpu_sources = Split('''
|
|
||||||
encumbered/cpu/full/bpred.cc
|
|
||||||
encumbered/cpu/full/commit.cc
|
|
||||||
encumbered/cpu/full/cpu.cc
|
|
||||||
encumbered/cpu/full/create_vector.cc
|
|
||||||
encumbered/cpu/full/cv_spec_state.cc
|
|
||||||
encumbered/cpu/full/dd_queue.cc
|
|
||||||
encumbered/cpu/full/dep_link.cc
|
|
||||||
encumbered/cpu/full/dispatch.cc
|
|
||||||
encumbered/cpu/full/dyn_inst.cc
|
|
||||||
encumbered/cpu/full/execute.cc
|
|
||||||
encumbered/cpu/full/fetch.cc
|
|
||||||
encumbered/cpu/full/floss_reasons.cc
|
|
||||||
encumbered/cpu/full/fu_pool.cc
|
|
||||||
encumbered/cpu/full/inst_fifo.cc
|
|
||||||
encumbered/cpu/full/instpipe.cc
|
|
||||||
encumbered/cpu/full/issue.cc
|
|
||||||
encumbered/cpu/full/ls_queue.cc
|
|
||||||
encumbered/cpu/full/machine_queue.cc
|
|
||||||
encumbered/cpu/full/pipetrace.cc
|
|
||||||
encumbered/cpu/full/readyq.cc
|
|
||||||
encumbered/cpu/full/reg_info.cc
|
|
||||||
encumbered/cpu/full/rob_station.cc
|
|
||||||
encumbered/cpu/full/spec_memory.cc
|
|
||||||
encumbered/cpu/full/spec_state.cc
|
|
||||||
encumbered/cpu/full/storebuffer.cc
|
|
||||||
encumbered/cpu/full/writeback.cc
|
|
||||||
encumbered/cpu/full/iq/iq_station.cc
|
|
||||||
encumbered/cpu/full/iq/iqueue.cc
|
|
||||||
encumbered/cpu/full/iq/segmented/chain_info.cc
|
|
||||||
encumbered/cpu/full/iq/segmented/chain_wire.cc
|
|
||||||
encumbered/cpu/full/iq/segmented/iq_seg.cc
|
|
||||||
encumbered/cpu/full/iq/segmented/iq_segmented.cc
|
|
||||||
encumbered/cpu/full/iq/segmented/seg_chain.cc
|
|
||||||
encumbered/cpu/full/iq/seznec/iq_seznec.cc
|
|
||||||
encumbered/cpu/full/iq/standard/iq_standard.cc
|
|
||||||
''')
|
|
||||||
|
|
||||||
trace_reader_sources = Split('''
|
trace_reader_sources = Split('''
|
||||||
cpu/trace/reader/mem_trace_reader.cc
|
cpu/trace/reader/mem_trace_reader.cc
|
||||||
cpu/trace/reader/ibm_reader.cc
|
cpu/trace/reader/ibm_reader.cc
|
||||||
|
@ -211,42 +173,9 @@ full_system_sources = Split('''
|
||||||
cpu/intr_control.cc
|
cpu/intr_control.cc
|
||||||
cpu/profile.cc
|
cpu/profile.cc
|
||||||
|
|
||||||
dev/alpha_console.cc
|
|
||||||
dev/baddev.cc
|
|
||||||
dev/disk_image.cc
|
|
||||||
dev/etherbus.cc
|
|
||||||
dev/etherdump.cc
|
|
||||||
dev/etherint.cc
|
|
||||||
dev/etherlink.cc
|
|
||||||
dev/etherpkt.cc
|
|
||||||
dev/ethertap.cc
|
|
||||||
dev/ide_ctrl.cc
|
|
||||||
dev/ide_disk.cc
|
|
||||||
dev/io_device.cc
|
|
||||||
dev/isa_fake.cc
|
|
||||||
dev/ns_gige.cc
|
|
||||||
dev/pciconfigall.cc
|
|
||||||
dev/pcidev.cc
|
|
||||||
dev/pcifake.cc
|
|
||||||
dev/pktfifo.cc
|
|
||||||
dev/platform.cc
|
|
||||||
dev/simconsole.cc
|
|
||||||
dev/simple_disk.cc
|
|
||||||
dev/tsunami.cc
|
|
||||||
dev/tsunami_cchip.cc
|
|
||||||
dev/tsunami_io.cc
|
|
||||||
dev/tsunami_fake.cc
|
|
||||||
dev/tsunami_pchip.cc
|
|
||||||
|
|
||||||
dev/uart.cc
|
dev/uart.cc
|
||||||
dev/uart8250.cc
|
dev/uart8250.cc
|
||||||
|
|
||||||
kern/kernel_stats.cc
|
|
||||||
kern/system_events.cc
|
|
||||||
kern/linux/events.cc
|
|
||||||
kern/linux/linux_syscalls.cc
|
|
||||||
kern/linux/printk.cc
|
|
||||||
|
|
||||||
mem/vport.cc
|
mem/vport.cc
|
||||||
|
|
||||||
sim/pseudo_inst.cc
|
sim/pseudo_inst.cc
|
||||||
|
@ -254,7 +183,6 @@ full_system_sources = Split('''
|
||||||
#dev/sinic.cc
|
#dev/sinic.cc
|
||||||
#dev/i8254xGBe.cc
|
#dev/i8254xGBe.cc
|
||||||
|
|
||||||
|
|
||||||
if env['TARGET_ISA'] == 'alpha':
|
if env['TARGET_ISA'] == 'alpha':
|
||||||
full_system_sources += Split('''
|
full_system_sources += Split('''
|
||||||
kern/tru64/dump_mbuf.cc
|
kern/tru64/dump_mbuf.cc
|
||||||
|
@ -263,26 +191,6 @@ if env['TARGET_ISA'] == 'alpha':
|
||||||
kern/tru64/tru64_syscalls.cc
|
kern/tru64/tru64_syscalls.cc
|
||||||
''')
|
''')
|
||||||
|
|
||||||
# turbolaser encumbered sources
|
|
||||||
turbolaser_sources = Split('''
|
|
||||||
encumbered/dev/dma.cc
|
|
||||||
encumbered/dev/etherdev.cc
|
|
||||||
encumbered/dev/scsi.cc
|
|
||||||
encumbered/dev/scsi_ctrl.cc
|
|
||||||
encumbered/dev/scsi_disk.cc
|
|
||||||
encumbered/dev/scsi_none.cc
|
|
||||||
encumbered/dev/tlaser_clock.cc
|
|
||||||
encumbered/dev/tlaser_ipi.cc
|
|
||||||
encumbered/dev/tlaser_mbox.cc
|
|
||||||
encumbered/dev/tlaser_mc146818.cc
|
|
||||||
encumbered/dev/tlaser_node.cc
|
|
||||||
encumbered/dev/tlaser_pcia.cc
|
|
||||||
encumbered/dev/tlaser_pcidev.cc
|
|
||||||
encumbered/dev/tlaser_serial.cc
|
|
||||||
encumbered/dev/turbolaser.cc
|
|
||||||
encumbered/dev/uart8530.cc
|
|
||||||
''')
|
|
||||||
|
|
||||||
# Syscall emulation (non-full-system) sources
|
# Syscall emulation (non-full-system) sources
|
||||||
syscall_emulation_sources = Split('''
|
syscall_emulation_sources = Split('''
|
||||||
mem/translating_port.cc
|
mem/translating_port.cc
|
||||||
|
@ -296,15 +204,6 @@ syscall_emulation_sources = Split('''
|
||||||
# kern/tru64/tru64.cc
|
# kern/tru64/tru64.cc
|
||||||
# ''')
|
# ''')
|
||||||
|
|
||||||
alpha_eio_sources = Split('''
|
|
||||||
encumbered/eio/exolex.cc
|
|
||||||
encumbered/eio/libexo.cc
|
|
||||||
encumbered/eio/eio.cc
|
|
||||||
''')
|
|
||||||
|
|
||||||
if env['TARGET_ISA'] == 'alpha':
|
|
||||||
syscall_emulation_sources += alpha_eio_sources
|
|
||||||
|
|
||||||
memtest_sources = Split('''
|
memtest_sources = Split('''
|
||||||
cpu/memtest/memtest.cc
|
cpu/memtest/memtest.cc
|
||||||
''')
|
''')
|
||||||
|
@ -318,22 +217,29 @@ env.Append(CPPPATH=Dir('.'))
|
||||||
# Add a flag defining what THE_ISA should be for all compilation
|
# Add a flag defining what THE_ISA should be for all compilation
|
||||||
env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())])
|
env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())])
|
||||||
|
|
||||||
arch_sources = SConscript('arch/SConscript', exports = 'env')
|
arch_sources = SConscript(os.path.join('arch', 'SConscript'), exports = 'env')
|
||||||
|
|
||||||
cpu_sources = SConscript('cpu/SConscript', exports = 'env')
|
cpu_sources = SConscript(os.path.join('cpu', 'SConscript'), exports = 'env')
|
||||||
|
|
||||||
# This is outside of cpu/SConscript since the source directory isn't
|
if env['FULL_SYSTEM']:
|
||||||
# underneath 'cpu'.
|
dev_sources = SConscript(os.path.join('dev', 'SConscript'),
|
||||||
if 'FullCPU' in env['CPU_MODELS']:
|
exports = 'env')
|
||||||
cpu_sources += full_cpu_sources
|
full_system_sources += dev_sources
|
||||||
|
|
||||||
|
kern_sources = SConscript(os.path.join('kern', 'SConscript'),
|
||||||
|
exports = 'env')
|
||||||
|
full_system_sources += kern_sources
|
||||||
|
|
||||||
# Set up complete list of sources based on configuration.
|
# Set up complete list of sources based on configuration.
|
||||||
sources = base_sources + arch_sources + cpu_sources
|
sources = base_sources + arch_sources + cpu_sources
|
||||||
|
|
||||||
|
# encumbered should be last because we're adding to some of the other groups
|
||||||
|
if isfile(joinpath(env['SRCDIR'], 'encumbered/SConscript')):
|
||||||
|
sources += SConscript('encumbered/SConscript', exports = 'env')
|
||||||
|
|
||||||
|
|
||||||
if env['FULL_SYSTEM']:
|
if env['FULL_SYSTEM']:
|
||||||
sources += full_system_sources
|
sources += full_system_sources
|
||||||
if env['ALPHA_TLASER']:
|
|
||||||
sources += turbolaser_sources
|
|
||||||
else:
|
else:
|
||||||
sources += syscall_emulation_sources
|
sources += syscall_emulation_sources
|
||||||
|
|
||||||
|
@ -401,8 +307,15 @@ def makeEnv(label, objsfx, strip = False, **kwargs):
|
||||||
envList.append(newEnv)
|
envList.append(newEnv)
|
||||||
|
|
||||||
# Debug binary
|
# Debug binary
|
||||||
|
# Solaris seems to have some issue with DWARF2 debugging information, it's ok
|
||||||
|
# with stabs though
|
||||||
|
if sys.platform == 'sunos5':
|
||||||
|
debug_flag = '-gstabs+'
|
||||||
|
else:
|
||||||
|
debug_flag = '-ggdb3'
|
||||||
|
|
||||||
makeEnv('debug', '.do',
|
makeEnv('debug', '.do',
|
||||||
CCFLAGS = Split('-g3 -gdwarf-2 -O0'),
|
CCFLAGS = Split('%s -O0' % debug_flag),
|
||||||
CPPDEFINES = 'DEBUG')
|
CPPDEFINES = 'DEBUG')
|
||||||
|
|
||||||
# Optimized binary
|
# Optimized binary
|
||||||
|
|
|
@ -49,10 +49,13 @@ sources = []
|
||||||
isa_switch_hdrs = Split('''
|
isa_switch_hdrs = Split('''
|
||||||
arguments.hh
|
arguments.hh
|
||||||
faults.hh
|
faults.hh
|
||||||
|
interrupts.hh
|
||||||
isa_traits.hh
|
isa_traits.hh
|
||||||
|
kernel_stats.hh
|
||||||
locked_mem.hh
|
locked_mem.hh
|
||||||
process.hh
|
process.hh
|
||||||
regfile.hh
|
regfile.hh
|
||||||
|
remote_gdb.hh
|
||||||
stacktrace.hh
|
stacktrace.hh
|
||||||
syscallreturn.hh
|
syscallreturn.hh
|
||||||
tlb.hh
|
tlb.hh
|
||||||
|
@ -61,36 +64,8 @@ isa_switch_hdrs = Split('''
|
||||||
vtophys.hh
|
vtophys.hh
|
||||||
''')
|
''')
|
||||||
|
|
||||||
# Generate the header. target[0] is the full path of the output
|
# Set up this directory to support switching headers
|
||||||
# header to generate. 'source' is a dummy variable, since we get the
|
env.make_switching_dir('arch', isa_switch_hdrs, env)
|
||||||
# list of ISAs from env['ALL_ISA_LIST'].
|
|
||||||
def gen_switch_hdr(target, source, env):
|
|
||||||
fname = str(target[0])
|
|
||||||
basename = os.path.basename(fname)
|
|
||||||
f = open(fname, 'w')
|
|
||||||
f.write('#include "arch/isa_specific.hh"\n')
|
|
||||||
cond = '#if'
|
|
||||||
for isa in env['ALL_ISA_LIST']:
|
|
||||||
f.write('%s THE_ISA == %s_ISA\n#include "arch/%s/%s"\n'
|
|
||||||
% (cond, isa.upper(), isa, basename))
|
|
||||||
cond = '#elif'
|
|
||||||
f.write('#else\n#error "THE_ISA not set"\n#endif\n')
|
|
||||||
f.close()
|
|
||||||
return 0
|
|
||||||
|
|
||||||
# String to print when generating header
|
|
||||||
def gen_switch_hdr_string(target, source, env):
|
|
||||||
return "Generating ISA switch header " + str(target[0])
|
|
||||||
|
|
||||||
# Build SCons Action object. 'varlist' specifies env vars that this
|
|
||||||
# action depends on; when env['ALL_ISA_LIST'] changes these actions
|
|
||||||
# should get re-executed.
|
|
||||||
switch_hdr_action = Action(gen_switch_hdr, gen_switch_hdr_string,
|
|
||||||
varlist=['ALL_ISA_LIST'])
|
|
||||||
|
|
||||||
# Instantiate actions for each header
|
|
||||||
for hdr in isa_switch_hdrs:
|
|
||||||
env.Command(hdr, [], switch_hdr_action)
|
|
||||||
|
|
||||||
#################################################################
|
#################################################################
|
||||||
#
|
#
|
||||||
|
|
|
@ -48,21 +48,29 @@ Import('env')
|
||||||
# Base sources used by all configurations.
|
# Base sources used by all configurations.
|
||||||
base_sources = Split('''
|
base_sources = Split('''
|
||||||
faults.cc
|
faults.cc
|
||||||
isa_traits.cc
|
floatregfile.cc
|
||||||
|
intregfile.cc
|
||||||
|
miscregfile.cc
|
||||||
|
regfile.cc
|
||||||
''')
|
''')
|
||||||
|
|
||||||
# Full-system sources
|
# Full-system sources
|
||||||
full_system_sources = Split('''
|
full_system_sources = Split('''
|
||||||
tlb.cc
|
|
||||||
arguments.cc
|
arguments.cc
|
||||||
ev5.cc
|
ev5.cc
|
||||||
osfpal.cc
|
|
||||||
stacktrace.cc
|
|
||||||
vtophys.cc
|
|
||||||
system.cc
|
|
||||||
freebsd/system.cc
|
freebsd/system.cc
|
||||||
|
idle_event.cc
|
||||||
|
ipr.cc
|
||||||
|
kernel_stats.cc
|
||||||
linux/system.cc
|
linux/system.cc
|
||||||
|
osfpal.cc
|
||||||
|
pagetable.cc
|
||||||
|
stacktrace.cc
|
||||||
|
remote_gdb.cc
|
||||||
|
system.cc
|
||||||
|
tlb.cc
|
||||||
tru64/system.cc
|
tru64/system.cc
|
||||||
|
vtophys.cc
|
||||||
''')
|
''')
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
|
|
||||||
using namespace AlphaISA;
|
using namespace AlphaISA;
|
||||||
|
|
||||||
AlphaArguments::Data::~Data()
|
Arguments::Data::~Data()
|
||||||
{
|
{
|
||||||
while (!data.empty()) {
|
while (!data.empty()) {
|
||||||
delete [] data.front();
|
delete [] data.front();
|
||||||
|
@ -44,7 +44,7 @@ AlphaArguments::Data::~Data()
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
AlphaArguments::Data::alloc(size_t size)
|
Arguments::Data::alloc(size_t size)
|
||||||
{
|
{
|
||||||
char *buf = new char[size];
|
char *buf = new char[size];
|
||||||
data.push_back(buf);
|
data.push_back(buf);
|
||||||
|
@ -52,7 +52,7 @@ AlphaArguments::Data::alloc(size_t size)
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
AlphaArguments::getArg(bool fp)
|
Arguments::getArg(bool fp)
|
||||||
{
|
{
|
||||||
if (number < 6) {
|
if (number < 6) {
|
||||||
if (fp)
|
if (fp)
|
||||||
|
|
|
@ -41,7 +41,7 @@ class ThreadContext;
|
||||||
|
|
||||||
namespace AlphaISA {
|
namespace AlphaISA {
|
||||||
|
|
||||||
class AlphaArguments
|
class Arguments
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
ThreadContext *tc;
|
ThreadContext *tc;
|
||||||
|
@ -65,62 +65,62 @@ class AlphaArguments
|
||||||
RefCountingPtr<Data> data;
|
RefCountingPtr<Data> data;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AlphaArguments(ThreadContext *ctx, int n = 0)
|
Arguments(ThreadContext *ctx, int n = 0)
|
||||||
: tc(ctx), number(n), data(NULL)
|
: tc(ctx), number(n), data(NULL)
|
||||||
{ assert(number >= 0); data = new Data;}
|
{ assert(number >= 0); data = new Data;}
|
||||||
AlphaArguments(const AlphaArguments &args)
|
Arguments(const Arguments &args)
|
||||||
: tc(args.tc), number(args.number), data(args.data) {}
|
: tc(args.tc), number(args.number), data(args.data) {}
|
||||||
~AlphaArguments() {}
|
~Arguments() {}
|
||||||
|
|
||||||
ThreadContext *getThreadContext() const { return tc; }
|
ThreadContext *getThreadContext() const { return tc; }
|
||||||
|
|
||||||
const AlphaArguments &operator=(const AlphaArguments &args) {
|
const Arguments &operator=(const Arguments &args) {
|
||||||
tc = args.tc;
|
tc = args.tc;
|
||||||
number = args.number;
|
number = args.number;
|
||||||
data = args.data;
|
data = args.data;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
AlphaArguments &operator++() {
|
Arguments &operator++() {
|
||||||
++number;
|
++number;
|
||||||
assert(number >= 0);
|
assert(number >= 0);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
AlphaArguments operator++(int) {
|
Arguments operator++(int) {
|
||||||
AlphaArguments args = *this;
|
Arguments args = *this;
|
||||||
++number;
|
++number;
|
||||||
assert(number >= 0);
|
assert(number >= 0);
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
AlphaArguments &operator--() {
|
Arguments &operator--() {
|
||||||
--number;
|
--number;
|
||||||
assert(number >= 0);
|
assert(number >= 0);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
AlphaArguments operator--(int) {
|
Arguments operator--(int) {
|
||||||
AlphaArguments args = *this;
|
Arguments args = *this;
|
||||||
--number;
|
--number;
|
||||||
assert(number >= 0);
|
assert(number >= 0);
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AlphaArguments &operator+=(int index) {
|
const Arguments &operator+=(int index) {
|
||||||
number += index;
|
number += index;
|
||||||
assert(number >= 0);
|
assert(number >= 0);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AlphaArguments &operator-=(int index) {
|
const Arguments &operator-=(int index) {
|
||||||
number -= index;
|
number -= index;
|
||||||
assert(number >= 0);
|
assert(number >= 0);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
AlphaArguments operator[](int index) {
|
Arguments operator[](int index) {
|
||||||
return AlphaArguments(tc, index);
|
return Arguments(tc, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
|
|
@ -31,16 +31,16 @@
|
||||||
|
|
||||||
#include "arch/alpha/faults.hh"
|
#include "arch/alpha/faults.hh"
|
||||||
#include "arch/alpha/isa_traits.hh"
|
#include "arch/alpha/isa_traits.hh"
|
||||||
|
#include "arch/alpha/kernel_stats.hh"
|
||||||
#include "arch/alpha/osfpal.hh"
|
#include "arch/alpha/osfpal.hh"
|
||||||
#include "arch/alpha/tlb.hh"
|
#include "arch/alpha/tlb.hh"
|
||||||
#include "base/kgdb.h"
|
#include "arch/alpha/kgdb.h"
|
||||||
#include "base/remote_gdb.hh"
|
#include "base/remote_gdb.hh"
|
||||||
#include "base/stats/events.hh"
|
#include "base/stats/events.hh"
|
||||||
#include "config/full_system.hh"
|
#include "config/full_system.hh"
|
||||||
#include "cpu/base.hh"
|
#include "cpu/base.hh"
|
||||||
#include "cpu/simple_thread.hh"
|
#include "cpu/simple_thread.hh"
|
||||||
#include "cpu/thread_context.hh"
|
#include "cpu/thread_context.hh"
|
||||||
#include "kern/kernel_stats.hh"
|
|
||||||
#include "sim/debug.hh"
|
#include "sim/debug.hh"
|
||||||
#include "sim/sim_exit.hh"
|
#include "sim/sim_exit.hh"
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ AlphaISA::initCPU(ThreadContext *tc, int cpuId)
|
||||||
tc->setIntReg(16, cpuId);
|
tc->setIntReg(16, cpuId);
|
||||||
tc->setIntReg(0, cpuId);
|
tc->setIntReg(0, cpuId);
|
||||||
|
|
||||||
AlphaFault *reset = new ResetFault;
|
AlphaISA::AlphaFault *reset = new AlphaISA::ResetFault;
|
||||||
|
|
||||||
tc->setPC(tc->readMiscReg(IPR_PAL_BASE) + reset->vect());
|
tc->setPC(tc->readMiscReg(IPR_PAL_BASE) + reset->vect());
|
||||||
tc->setNextPC(tc->readPC() + sizeof(MachInst));
|
tc->setNextPC(tc->readPC() + sizeof(MachInst));
|
||||||
|
@ -147,7 +147,7 @@ AlphaISA::zeroRegisters(CPU *cpu)
|
||||||
Fault
|
Fault
|
||||||
SimpleThread::hwrei()
|
SimpleThread::hwrei()
|
||||||
{
|
{
|
||||||
if (!inPalMode())
|
if (!(readPC() & 0x3))
|
||||||
return new UnimplementedOpcodeFault;
|
return new UnimplementedOpcodeFault;
|
||||||
|
|
||||||
setNextPC(readMiscReg(AlphaISA::IPR_EXC_ADDR));
|
setNextPC(readMiscReg(AlphaISA::IPR_EXC_ADDR));
|
||||||
|
@ -176,7 +176,7 @@ AlphaISA::MiscRegFile::getDataAsid()
|
||||||
}
|
}
|
||||||
|
|
||||||
AlphaISA::MiscReg
|
AlphaISA::MiscReg
|
||||||
AlphaISA::MiscRegFile::readIpr(int idx, Fault &fault, ThreadContext *tc)
|
AlphaISA::MiscRegFile::readIpr(int idx, ThreadContext *tc)
|
||||||
{
|
{
|
||||||
uint64_t retval = 0; // return value, default 0
|
uint64_t retval = 0; // return value, default 0
|
||||||
|
|
||||||
|
@ -269,12 +269,12 @@ AlphaISA::MiscRegFile::readIpr(int idx, Fault &fault, ThreadContext *tc)
|
||||||
case AlphaISA::IPR_DTB_IAP:
|
case AlphaISA::IPR_DTB_IAP:
|
||||||
case AlphaISA::IPR_ITB_IA:
|
case AlphaISA::IPR_ITB_IA:
|
||||||
case AlphaISA::IPR_ITB_IAP:
|
case AlphaISA::IPR_ITB_IAP:
|
||||||
fault = new UnimplementedOpcodeFault;
|
panic("Tried to read write only register %d\n", idx);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// invalid IPR
|
// invalid IPR
|
||||||
fault = new UnimplementedOpcodeFault;
|
panic("Tried to read from invalid ipr %d\n", idx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,13 +286,13 @@ AlphaISA::MiscRegFile::readIpr(int idx, Fault &fault, ThreadContext *tc)
|
||||||
int break_ipl = -1;
|
int break_ipl = -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Fault
|
void
|
||||||
AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc)
|
AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc)
|
||||||
{
|
{
|
||||||
uint64_t old;
|
uint64_t old;
|
||||||
|
|
||||||
if (tc->misspeculating())
|
if (tc->misspeculating())
|
||||||
return NoFault;
|
return;
|
||||||
|
|
||||||
switch (idx) {
|
switch (idx) {
|
||||||
case AlphaISA::IPR_PALtemp0:
|
case AlphaISA::IPR_PALtemp0:
|
||||||
|
@ -379,10 +379,10 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc)
|
||||||
case AlphaISA::IPR_DTB_CM:
|
case AlphaISA::IPR_DTB_CM:
|
||||||
if (val & 0x18) {
|
if (val & 0x18) {
|
||||||
if (tc->getKernelStats())
|
if (tc->getKernelStats())
|
||||||
tc->getKernelStats()->mode(Kernel::user, tc);
|
tc->getKernelStats()->mode(TheISA::Kernel::user, tc);
|
||||||
} else {
|
} else {
|
||||||
if (tc->getKernelStats())
|
if (tc->getKernelStats())
|
||||||
tc->getKernelStats()->mode(Kernel::kernel, tc);
|
tc->getKernelStats()->mode(TheISA::Kernel::kernel, tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
case AlphaISA::IPR_ICM:
|
case AlphaISA::IPR_ICM:
|
||||||
|
@ -443,7 +443,7 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc)
|
||||||
case AlphaISA::IPR_ITB_PTE_TEMP:
|
case AlphaISA::IPR_ITB_PTE_TEMP:
|
||||||
case AlphaISA::IPR_DTB_PTE_TEMP:
|
case AlphaISA::IPR_DTB_PTE_TEMP:
|
||||||
// read-only registers
|
// read-only registers
|
||||||
return new UnimplementedOpcodeFault;
|
panic("Tried to write read only ipr %d\n", idx);
|
||||||
|
|
||||||
case AlphaISA::IPR_HWINT_CLR:
|
case AlphaISA::IPR_HWINT_CLR:
|
||||||
case AlphaISA::IPR_SL_XMIT:
|
case AlphaISA::IPR_SL_XMIT:
|
||||||
|
@ -547,18 +547,17 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// invalid IPR
|
// invalid IPR
|
||||||
return new UnimplementedOpcodeFault;
|
panic("Tried to write to invalid ipr %d\n", idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// no error...
|
// no error...
|
||||||
return NoFault;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
AlphaISA::copyIprs(ThreadContext *src, ThreadContext *dest)
|
AlphaISA::copyIprs(ThreadContext *src, ThreadContext *dest)
|
||||||
{
|
{
|
||||||
for (int i = IPR_Base_DepTag; i < NumInternalProcRegs; ++i) {
|
for (int i = 0; i < NumInternalProcRegs; ++i) {
|
||||||
dest->setMiscReg(i, src->readMiscReg(i));
|
dest->setMiscReg(i, src->readMiscReg(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,7 +125,7 @@ void AlphaFault::invoke(ThreadContext * tc)
|
||||||
countStat()++;
|
countStat()++;
|
||||||
|
|
||||||
// exception restart address
|
// exception restart address
|
||||||
if (setRestartAddress() || !tc->inPalMode())
|
if (setRestartAddress() || !(tc->readPC() & 0x3))
|
||||||
tc->setMiscReg(AlphaISA::IPR_EXC_ADDR, tc->readPC());
|
tc->setMiscReg(AlphaISA::IPR_EXC_ADDR, tc->readPC());
|
||||||
|
|
||||||
if (skipFaultingInstruction()) {
|
if (skipFaultingInstruction()) {
|
||||||
|
|
49
src/arch/alpha/floatregfile.cc
Normal file
49
src/arch/alpha/floatregfile.cc
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003-2005 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Steve Reinhardt
|
||||||
|
* Gabe Black
|
||||||
|
* Kevin Lim
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "arch/alpha/floatregfile.hh"
|
||||||
|
#include "sim/serialize.hh"
|
||||||
|
|
||||||
|
namespace AlphaISA
|
||||||
|
{
|
||||||
|
void
|
||||||
|
FloatRegFile::serialize(std::ostream &os)
|
||||||
|
{
|
||||||
|
SERIALIZE_ARRAY(q, NumFloatRegs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FloatRegFile::unserialize(Checkpoint *cp, const std::string §ion)
|
||||||
|
{
|
||||||
|
UNSERIALIZE_ARRAY(q, NumFloatRegs);
|
||||||
|
}
|
||||||
|
}
|
68
src/arch/alpha/floatregfile.hh
Normal file
68
src/arch/alpha/floatregfile.hh
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003-2005 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Steve Reinhardt
|
||||||
|
* Gabe Black
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ARCH_ALPHA_FLOATREGFILE_HH__
|
||||||
|
#define __ARCH_ALPHA_FLOATREGFILE_HH__
|
||||||
|
|
||||||
|
#include "arch/alpha/isa_traits.hh"
|
||||||
|
#include "arch/alpha/types.hh"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
class Checkpoint;
|
||||||
|
|
||||||
|
namespace AlphaISA
|
||||||
|
{
|
||||||
|
static inline std::string getFloatRegName(RegIndex)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
class FloatRegFile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
union {
|
||||||
|
uint64_t q[NumFloatRegs]; // integer qword view
|
||||||
|
double d[NumFloatRegs]; // double-precision floating point view
|
||||||
|
};
|
||||||
|
|
||||||
|
void serialize(std::ostream &os);
|
||||||
|
|
||||||
|
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{ bzero(d, sizeof(d)); }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
45
src/arch/alpha/idle_event.cc
Normal file
45
src/arch/alpha/idle_event.cc
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2004-2005 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Lisa Hsu
|
||||||
|
* Nathan Binkert
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "arch/alpha/idle_event.hh"
|
||||||
|
#include "arch/alpha/kernel_stats.hh"
|
||||||
|
#include "cpu/thread_context.hh"
|
||||||
|
|
||||||
|
using namespace TheISA;
|
||||||
|
|
||||||
|
void
|
||||||
|
IdleStartEvent::process(ThreadContext *tc)
|
||||||
|
{
|
||||||
|
if (tc->getKernelStats())
|
||||||
|
tc->getKernelStats()->setIdleProcess(
|
||||||
|
tc->readMiscReg(AlphaISA::IPR_PALtemp23), tc);
|
||||||
|
remove();
|
||||||
|
}
|
47
src/arch/alpha/idle_event.hh
Normal file
47
src/arch/alpha/idle_event.hh
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2004-2005 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Nathan Binkert
|
||||||
|
* Lisa Hsu
|
||||||
|
* Ali Saidi
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __KERN_ALPHA_IDLE_EVENT_HH__
|
||||||
|
#define __KERN_ALPHA_IDLE_EVENT_HH__
|
||||||
|
|
||||||
|
#include "cpu/pc_event.hh"
|
||||||
|
|
||||||
|
class IdleStartEvent : public PCEvent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IdleStartEvent(PCEventQueue *q, const std::string &desc, Addr addr)
|
||||||
|
: PCEvent(q, desc, addr)
|
||||||
|
{}
|
||||||
|
virtual void process(ThreadContext *tc);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __KERN_ALPHA_IDLE_EVENT_HH__
|
166
src/arch/alpha/interrupts.hh
Normal file
166
src/arch/alpha/interrupts.hh
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Steve Reinhardt
|
||||||
|
* Kevin Lim
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ARCH_ALPHA_INTERRUPT_HH__
|
||||||
|
#define __ARCH_ALPHA_INTERRUPT_HH__
|
||||||
|
|
||||||
|
#include "arch/alpha/faults.hh"
|
||||||
|
#include "arch/alpha/isa_traits.hh"
|
||||||
|
#include "cpu/thread_context.hh"
|
||||||
|
|
||||||
|
namespace AlphaISA
|
||||||
|
{
|
||||||
|
class Interrupts
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
uint64_t interrupts[NumInterruptLevels];
|
||||||
|
uint64_t intstatus;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Interrupts()
|
||||||
|
{
|
||||||
|
memset(interrupts, 0, sizeof(interrupts));
|
||||||
|
intstatus = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void post(int int_num, int index)
|
||||||
|
{
|
||||||
|
DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
|
||||||
|
|
||||||
|
if (int_num < 0 || int_num >= NumInterruptLevels)
|
||||||
|
panic("int_num out of bounds\n");
|
||||||
|
|
||||||
|
if (index < 0 || index >= sizeof(uint64_t) * 8)
|
||||||
|
panic("int_num out of bounds\n");
|
||||||
|
|
||||||
|
interrupts[int_num] |= 1 << index;
|
||||||
|
intstatus |= (ULL(1) << int_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear(int int_num, int index)
|
||||||
|
{
|
||||||
|
DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
|
||||||
|
|
||||||
|
if (int_num < 0 || int_num >= TheISA::NumInterruptLevels)
|
||||||
|
panic("int_num out of bounds\n");
|
||||||
|
|
||||||
|
if (index < 0 || index >= sizeof(uint64_t) * 8)
|
||||||
|
panic("int_num out of bounds\n");
|
||||||
|
|
||||||
|
interrupts[int_num] &= ~(1 << index);
|
||||||
|
if (interrupts[int_num] == 0)
|
||||||
|
intstatus &= ~(ULL(1) << int_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_all()
|
||||||
|
{
|
||||||
|
DPRINTF(Interrupt, "Interrupts all cleared\n");
|
||||||
|
|
||||||
|
memset(interrupts, 0, sizeof(interrupts));
|
||||||
|
intstatus = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serialize(std::ostream &os)
|
||||||
|
{
|
||||||
|
SERIALIZE_ARRAY(interrupts, NumInterruptLevels);
|
||||||
|
SERIALIZE_SCALAR(intstatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
void unserialize(Checkpoint *cp, const std::string §ion)
|
||||||
|
{
|
||||||
|
UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels);
|
||||||
|
UNSERIALIZE_SCALAR(intstatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check_interrupts(ThreadContext * tc) const
|
||||||
|
{
|
||||||
|
return (intstatus != 0) && !(tc->readPC() & 0x3);
|
||||||
|
}
|
||||||
|
|
||||||
|
Fault getInterrupt(ThreadContext * tc)
|
||||||
|
{
|
||||||
|
int ipl = 0;
|
||||||
|
int summary = 0;
|
||||||
|
|
||||||
|
if (tc->readMiscReg(IPR_ASTRR))
|
||||||
|
panic("asynchronous traps not implemented\n");
|
||||||
|
|
||||||
|
if (tc->readMiscReg(IPR_SIRR)) {
|
||||||
|
for (int i = INTLEVEL_SOFTWARE_MIN;
|
||||||
|
i < INTLEVEL_SOFTWARE_MAX; i++) {
|
||||||
|
if (tc->readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
|
||||||
|
// See table 4-19 of 21164 hardware reference
|
||||||
|
ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
|
||||||
|
summary |= (ULL(1) << i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t interrupts = intstatus;
|
||||||
|
if (interrupts) {
|
||||||
|
for (int i = INTLEVEL_EXTERNAL_MIN;
|
||||||
|
i < INTLEVEL_EXTERNAL_MAX; i++) {
|
||||||
|
if (interrupts & (ULL(1) << i)) {
|
||||||
|
// See table 4-19 of 21164 hardware reference
|
||||||
|
ipl = i;
|
||||||
|
summary |= (ULL(1) << i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ipl && ipl > tc->readMiscReg(IPR_IPLR)) {
|
||||||
|
tc->setMiscReg(IPR_ISR, summary);
|
||||||
|
tc->setMiscReg(IPR_INTID, ipl);
|
||||||
|
|
||||||
|
/* The following needs to be added back in somehow */
|
||||||
|
// Checker needs to know these two registers were updated.
|
||||||
|
/*#if USE_CHECKER
|
||||||
|
if (this->checker) {
|
||||||
|
this->checker->threadBase()->setMiscReg(IPR_ISR, summary);
|
||||||
|
this->checker->threadBase()->setMiscReg(IPR_INTID, ipl);
|
||||||
|
}
|
||||||
|
#endif*/
|
||||||
|
|
||||||
|
DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
|
||||||
|
tc->readMiscReg(IPR_IPLR), ipl, summary);
|
||||||
|
|
||||||
|
return new InterruptFault;
|
||||||
|
} else {
|
||||||
|
return NoFault;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
65
src/arch/alpha/intregfile.cc
Normal file
65
src/arch/alpha/intregfile.cc
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003-2005 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Steve Reinhardt
|
||||||
|
* Gabe Black
|
||||||
|
* Kevin Lim
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "arch/alpha/isa_traits.hh"
|
||||||
|
#include "arch/alpha/intregfile.hh"
|
||||||
|
#include "sim/serialize.hh"
|
||||||
|
|
||||||
|
namespace AlphaISA
|
||||||
|
{
|
||||||
|
#if FULL_SYSTEM
|
||||||
|
const int reg_redir[AlphaISA::NumIntRegs] = {
|
||||||
|
/* 0 */ 0, 1, 2, 3, 4, 5, 6, 7,
|
||||||
|
/* 8 */ 32, 33, 34, 35, 36, 37, 38, 15,
|
||||||
|
/* 16 */ 16, 17, 18, 19, 20, 21, 22, 23,
|
||||||
|
/* 24 */ 24, 39, 26, 27, 28, 29, 30, 31 };
|
||||||
|
#else
|
||||||
|
const int reg_redir[AlphaISA::NumIntRegs] = {
|
||||||
|
/* 0 */ 0, 1, 2, 3, 4, 5, 6, 7,
|
||||||
|
/* 8 */ 8, 9, 10, 11, 12, 13, 14, 15,
|
||||||
|
/* 16 */ 16, 17, 18, 19, 20, 21, 22, 23,
|
||||||
|
/* 24 */ 24, 25, 26, 27, 28, 29, 30, 31 };
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
IntRegFile::serialize(std::ostream &os)
|
||||||
|
{
|
||||||
|
SERIALIZE_ARRAY(regs, NumIntRegs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IntRegFile::unserialize(Checkpoint *cp, const std::string §ion)
|
||||||
|
{
|
||||||
|
UNSERIALIZE_ARRAY(regs, NumIntRegs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
78
src/arch/alpha/intregfile.hh
Normal file
78
src/arch/alpha/intregfile.hh
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003-2005 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Steve Reinhardt
|
||||||
|
* Gabe Black
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ARCH_ALPHA_INTREGFILE_HH__
|
||||||
|
#define __ARCH_ALPHA_INTREGFILE_HH__
|
||||||
|
|
||||||
|
#include "arch/alpha/types.hh"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <strings.h>
|
||||||
|
|
||||||
|
class Checkpoint;
|
||||||
|
|
||||||
|
namespace AlphaISA
|
||||||
|
{
|
||||||
|
static inline std::string getIntRegName(RegIndex)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// redirected register map, really only used for the full system case.
|
||||||
|
extern const int reg_redir[NumIntRegs];
|
||||||
|
|
||||||
|
class IntRegFile
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
IntReg regs[NumIntRegs];
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
IntReg readReg(int intReg)
|
||||||
|
{
|
||||||
|
return regs[intReg];
|
||||||
|
}
|
||||||
|
|
||||||
|
void setReg(int intReg, const IntReg &val)
|
||||||
|
{
|
||||||
|
regs[intReg] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serialize(std::ostream &os);
|
||||||
|
|
||||||
|
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{ bzero(regs, sizeof(regs)); }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
140
src/arch/alpha/ipr.cc
Normal file
140
src/arch/alpha/ipr.cc
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003-2005 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Gabe Black
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "arch/alpha/ipr.hh"
|
||||||
|
|
||||||
|
namespace AlphaISA
|
||||||
|
{
|
||||||
|
md_ipr_names MiscRegIndexToIpr[NumInternalProcRegs] =
|
||||||
|
{
|
||||||
|
//Write only
|
||||||
|
RAW_IPR_HWINT_CLR, // H/W interrupt clear register
|
||||||
|
RAW_IPR_SL_XMIT, // serial line transmit register
|
||||||
|
RAW_IPR_DC_FLUSH,
|
||||||
|
RAW_IPR_IC_FLUSH, // instruction cache flush control
|
||||||
|
RAW_IPR_ALT_MODE, // alternate mode register
|
||||||
|
RAW_IPR_DTB_IA, // DTLB invalidate all register
|
||||||
|
RAW_IPR_DTB_IAP, // DTLB invalidate all process register
|
||||||
|
RAW_IPR_ITB_IA, // ITLB invalidate all register
|
||||||
|
RAW_IPR_ITB_IAP, // ITLB invalidate all process register
|
||||||
|
|
||||||
|
//Read only
|
||||||
|
RAW_IPR_INTID, // interrupt ID register
|
||||||
|
RAW_IPR_SL_RCV, // serial line receive register
|
||||||
|
RAW_IPR_MM_STAT, // data MMU fault status register
|
||||||
|
RAW_IPR_ITB_PTE_TEMP, // ITLB page table entry temp register
|
||||||
|
RAW_IPR_DTB_PTE_TEMP, // DTLB page table entry temporary register
|
||||||
|
|
||||||
|
RAW_IPR_ISR, // interrupt summary register
|
||||||
|
RAW_IPR_ITB_TAG, // ITLB tag register
|
||||||
|
RAW_IPR_ITB_PTE, // ITLB page table entry register
|
||||||
|
RAW_IPR_ITB_ASN, // ITLB address space register
|
||||||
|
RAW_IPR_ITB_IS, // ITLB invalidate select register
|
||||||
|
RAW_IPR_SIRR, // software interrupt request register
|
||||||
|
RAW_IPR_ASTRR, // asynchronous system trap request register
|
||||||
|
RAW_IPR_ASTER, // asynchronous system trap enable register
|
||||||
|
RAW_IPR_EXC_ADDR, // exception address register
|
||||||
|
RAW_IPR_EXC_SUM, // exception summary register
|
||||||
|
RAW_IPR_EXC_MASK, // exception mask register
|
||||||
|
RAW_IPR_PAL_BASE, // PAL base address register
|
||||||
|
RAW_IPR_ICM, // instruction current mode
|
||||||
|
RAW_IPR_IPLR, // interrupt priority level register
|
||||||
|
RAW_IPR_IFAULT_VA_FORM, // formatted faulting virtual addr register
|
||||||
|
RAW_IPR_IVPTBR, // virtual page table base register
|
||||||
|
RAW_IPR_ICSR, // instruction control and status register
|
||||||
|
RAW_IPR_IC_PERR_STAT, // inst cache parity error status register
|
||||||
|
RAW_IPR_PMCTR, // performance counter register
|
||||||
|
|
||||||
|
// PAL temporary registers...
|
||||||
|
// register meanings gleaned from osfpal.s source code
|
||||||
|
RAW_IPR_PALtemp0, // local scratch
|
||||||
|
RAW_IPR_PALtemp1, // local scratch
|
||||||
|
RAW_IPR_PALtemp2, // entUna
|
||||||
|
RAW_IPR_PALtemp3, // CPU specific impure area pointer
|
||||||
|
RAW_IPR_PALtemp4, // memory management temp
|
||||||
|
RAW_IPR_PALtemp5, // memory management temp
|
||||||
|
RAW_IPR_PALtemp6, // memory management temp
|
||||||
|
RAW_IPR_PALtemp7, // entIF
|
||||||
|
RAW_IPR_PALtemp8, // intmask
|
||||||
|
RAW_IPR_PALtemp9, // entSys
|
||||||
|
RAW_IPR_PALtemp10, // ??
|
||||||
|
RAW_IPR_PALtemp11, // entInt
|
||||||
|
RAW_IPR_PALtemp12, // entArith
|
||||||
|
RAW_IPR_PALtemp13, // reserved for platform specific PAL
|
||||||
|
RAW_IPR_PALtemp14, // reserved for platform specific PAL
|
||||||
|
RAW_IPR_PALtemp15, // reserved for platform specific PAL
|
||||||
|
RAW_IPR_PALtemp16, // scratch / whami<7:0> / mces<4:0>
|
||||||
|
RAW_IPR_PALtemp17, // sysval
|
||||||
|
RAW_IPR_PALtemp18, // usp
|
||||||
|
RAW_IPR_PALtemp19, // ksp
|
||||||
|
RAW_IPR_PALtemp20, // PTBR
|
||||||
|
RAW_IPR_PALtemp21, // entMM
|
||||||
|
RAW_IPR_PALtemp22, // kgp
|
||||||
|
RAW_IPR_PALtemp23, // PCBB
|
||||||
|
|
||||||
|
RAW_IPR_DTB_ASN, // DTLB address space number register
|
||||||
|
RAW_IPR_DTB_CM, // DTLB current mode register
|
||||||
|
RAW_IPR_DTB_TAG, // DTLB tag register
|
||||||
|
RAW_IPR_DTB_PTE, // DTLB page table entry register
|
||||||
|
|
||||||
|
RAW_IPR_VA, // fault virtual address register
|
||||||
|
RAW_IPR_VA_FORM, // formatted virtual address register
|
||||||
|
RAW_IPR_MVPTBR, // MTU virtual page table base register
|
||||||
|
RAW_IPR_DTB_IS, // DTLB invalidate single register
|
||||||
|
RAW_IPR_CC, // cycle counter register
|
||||||
|
RAW_IPR_CC_CTL, // cycle counter control register
|
||||||
|
RAW_IPR_MCSR, // MTU control register
|
||||||
|
|
||||||
|
RAW_IPR_DC_PERR_STAT, // Dcache parity error status register
|
||||||
|
RAW_IPR_DC_TEST_CTL, // Dcache test tag control register
|
||||||
|
RAW_IPR_DC_TEST_TAG, // Dcache test tag register
|
||||||
|
RAW_IPR_DC_TEST_TAG_TEMP, // Dcache test tag temporary register
|
||||||
|
RAW_IPR_DC_MODE, // Dcache mode register
|
||||||
|
RAW_IPR_MAF_MODE // miss address file mode register
|
||||||
|
};
|
||||||
|
|
||||||
|
int IprToMiscRegIndex[MaxInternalProcRegs];
|
||||||
|
|
||||||
|
void initializeIprTable()
|
||||||
|
{
|
||||||
|
static bool initialized = false;
|
||||||
|
if(initialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memset(IprToMiscRegIndex, -1, MaxInternalProcRegs * sizeof(int));
|
||||||
|
|
||||||
|
for(int x = 0; x < NumInternalProcRegs; x++)
|
||||||
|
IprToMiscRegIndex[MiscRegIndexToIpr[x]] = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
237
src/arch/alpha/ipr.hh
Normal file
237
src/arch/alpha/ipr.hh
Normal file
|
@ -0,0 +1,237 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003-2005 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Steve Reinhardt
|
||||||
|
* Gabe Black
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ARCH_ALPHA_IPR_HH__
|
||||||
|
#define __ARCH_ALPHA_IPR_HH__
|
||||||
|
|
||||||
|
namespace AlphaISA
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Internal Processor Reigsters
|
||||||
|
//
|
||||||
|
enum md_ipr_names
|
||||||
|
{
|
||||||
|
RAW_IPR_ISR = 0x100, // interrupt summary register
|
||||||
|
RAW_IPR_ITB_TAG = 0x101, // ITLB tag register
|
||||||
|
RAW_IPR_ITB_PTE = 0x102, // ITLB page table entry register
|
||||||
|
RAW_IPR_ITB_ASN = 0x103, // ITLB address space register
|
||||||
|
RAW_IPR_ITB_PTE_TEMP = 0x104, // ITLB page table entry temp register
|
||||||
|
RAW_IPR_ITB_IA = 0x105, // ITLB invalidate all register
|
||||||
|
RAW_IPR_ITB_IAP = 0x106, // ITLB invalidate all process register
|
||||||
|
RAW_IPR_ITB_IS = 0x107, // ITLB invalidate select register
|
||||||
|
RAW_IPR_SIRR = 0x108, // software interrupt request register
|
||||||
|
RAW_IPR_ASTRR = 0x109, // asynchronous system trap request register
|
||||||
|
RAW_IPR_ASTER = 0x10a, // asynchronous system trap enable register
|
||||||
|
RAW_IPR_EXC_ADDR = 0x10b, // exception address register
|
||||||
|
RAW_IPR_EXC_SUM = 0x10c, // exception summary register
|
||||||
|
RAW_IPR_EXC_MASK = 0x10d, // exception mask register
|
||||||
|
RAW_IPR_PAL_BASE = 0x10e, // PAL base address register
|
||||||
|
RAW_IPR_ICM = 0x10f, // instruction current mode
|
||||||
|
RAW_IPR_IPLR = 0x110, // interrupt priority level register
|
||||||
|
RAW_IPR_INTID = 0x111, // interrupt ID register
|
||||||
|
RAW_IPR_IFAULT_VA_FORM = 0x112, // formatted faulting virtual addr register
|
||||||
|
RAW_IPR_IVPTBR = 0x113, // virtual page table base register
|
||||||
|
RAW_IPR_HWINT_CLR = 0x115, // H/W interrupt clear register
|
||||||
|
RAW_IPR_SL_XMIT = 0x116, // serial line transmit register
|
||||||
|
RAW_IPR_SL_RCV = 0x117, // serial line receive register
|
||||||
|
RAW_IPR_ICSR = 0x118, // instruction control and status register
|
||||||
|
RAW_IPR_IC_FLUSH = 0x119, // instruction cache flush control
|
||||||
|
RAW_IPR_IC_PERR_STAT = 0x11a, // inst cache parity error status register
|
||||||
|
RAW_IPR_PMCTR = 0x11c, // performance counter register
|
||||||
|
|
||||||
|
// PAL temporary registers...
|
||||||
|
// register meanings gleaned from osfpal.s source code
|
||||||
|
RAW_IPR_PALtemp0 = 0x140, // local scratch
|
||||||
|
RAW_IPR_PALtemp1 = 0x141, // local scratch
|
||||||
|
RAW_IPR_PALtemp2 = 0x142, // entUna
|
||||||
|
RAW_IPR_PALtemp3 = 0x143, // CPU specific impure area pointer
|
||||||
|
RAW_IPR_PALtemp4 = 0x144, // memory management temp
|
||||||
|
RAW_IPR_PALtemp5 = 0x145, // memory management temp
|
||||||
|
RAW_IPR_PALtemp6 = 0x146, // memory management temp
|
||||||
|
RAW_IPR_PALtemp7 = 0x147, // entIF
|
||||||
|
RAW_IPR_PALtemp8 = 0x148, // intmask
|
||||||
|
RAW_IPR_PALtemp9 = 0x149, // entSys
|
||||||
|
RAW_IPR_PALtemp10 = 0x14a, // ??
|
||||||
|
RAW_IPR_PALtemp11 = 0x14b, // entInt
|
||||||
|
RAW_IPR_PALtemp12 = 0x14c, // entArith
|
||||||
|
RAW_IPR_PALtemp13 = 0x14d, // reserved for platform specific PAL
|
||||||
|
RAW_IPR_PALtemp14 = 0x14e, // reserved for platform specific PAL
|
||||||
|
RAW_IPR_PALtemp15 = 0x14f, // reserved for platform specific PAL
|
||||||
|
RAW_IPR_PALtemp16 = 0x150, // scratch / whami<7:0> / mces<4:0>
|
||||||
|
RAW_IPR_PALtemp17 = 0x151, // sysval
|
||||||
|
RAW_IPR_PALtemp18 = 0x152, // usp
|
||||||
|
RAW_IPR_PALtemp19 = 0x153, // ksp
|
||||||
|
RAW_IPR_PALtemp20 = 0x154, // PTBR
|
||||||
|
RAW_IPR_PALtemp21 = 0x155, // entMM
|
||||||
|
RAW_IPR_PALtemp22 = 0x156, // kgp
|
||||||
|
RAW_IPR_PALtemp23 = 0x157, // PCBB
|
||||||
|
|
||||||
|
RAW_IPR_DTB_ASN = 0x200, // DTLB address space number register
|
||||||
|
RAW_IPR_DTB_CM = 0x201, // DTLB current mode register
|
||||||
|
RAW_IPR_DTB_TAG = 0x202, // DTLB tag register
|
||||||
|
RAW_IPR_DTB_PTE = 0x203, // DTLB page table entry register
|
||||||
|
RAW_IPR_DTB_PTE_TEMP = 0x204, // DTLB page table entry temporary register
|
||||||
|
|
||||||
|
RAW_IPR_MM_STAT = 0x205, // data MMU fault status register
|
||||||
|
RAW_IPR_VA = 0x206, // fault virtual address register
|
||||||
|
RAW_IPR_VA_FORM = 0x207, // formatted virtual address register
|
||||||
|
RAW_IPR_MVPTBR = 0x208, // MTU virtual page table base register
|
||||||
|
RAW_IPR_DTB_IAP = 0x209, // DTLB invalidate all process register
|
||||||
|
RAW_IPR_DTB_IA = 0x20a, // DTLB invalidate all register
|
||||||
|
RAW_IPR_DTB_IS = 0x20b, // DTLB invalidate single register
|
||||||
|
RAW_IPR_ALT_MODE = 0x20c, // alternate mode register
|
||||||
|
RAW_IPR_CC = 0x20d, // cycle counter register
|
||||||
|
RAW_IPR_CC_CTL = 0x20e, // cycle counter control register
|
||||||
|
RAW_IPR_MCSR = 0x20f, // MTU control register
|
||||||
|
|
||||||
|
RAW_IPR_DC_FLUSH = 0x210,
|
||||||
|
RAW_IPR_DC_PERR_STAT = 0x212, // Dcache parity error status register
|
||||||
|
RAW_IPR_DC_TEST_CTL = 0x213, // Dcache test tag control register
|
||||||
|
RAW_IPR_DC_TEST_TAG = 0x214, // Dcache test tag register
|
||||||
|
RAW_IPR_DC_TEST_TAG_TEMP = 0x215, // Dcache test tag temporary register
|
||||||
|
RAW_IPR_DC_MODE = 0x216, // Dcache mode register
|
||||||
|
RAW_IPR_MAF_MODE = 0x217, // miss address file mode register
|
||||||
|
|
||||||
|
MaxInternalProcRegs // number of IPR registers
|
||||||
|
};
|
||||||
|
|
||||||
|
enum MiscRegIpr
|
||||||
|
{
|
||||||
|
//Write only
|
||||||
|
MinWriteOnlyIpr,
|
||||||
|
IPR_HWINT_CLR = MinWriteOnlyIpr,
|
||||||
|
IPR_SL_XMIT,
|
||||||
|
IPR_DC_FLUSH,
|
||||||
|
IPR_IC_FLUSH,
|
||||||
|
IPR_ALT_MODE,
|
||||||
|
IPR_DTB_IA,
|
||||||
|
IPR_DTB_IAP,
|
||||||
|
IPR_ITB_IA,
|
||||||
|
MaxWriteOnlyIpr,
|
||||||
|
IPR_ITB_IAP = MaxWriteOnlyIpr,
|
||||||
|
|
||||||
|
//Read only
|
||||||
|
MinReadOnlyIpr,
|
||||||
|
IPR_INTID = MinReadOnlyIpr,
|
||||||
|
IPR_SL_RCV,
|
||||||
|
IPR_MM_STAT,
|
||||||
|
IPR_ITB_PTE_TEMP,
|
||||||
|
MaxReadOnlyIpr,
|
||||||
|
IPR_DTB_PTE_TEMP = MaxReadOnlyIpr,
|
||||||
|
|
||||||
|
IPR_ISR,
|
||||||
|
IPR_ITB_TAG,
|
||||||
|
IPR_ITB_PTE,
|
||||||
|
IPR_ITB_ASN,
|
||||||
|
IPR_ITB_IS,
|
||||||
|
IPR_SIRR,
|
||||||
|
IPR_ASTRR,
|
||||||
|
IPR_ASTER,
|
||||||
|
IPR_EXC_ADDR,
|
||||||
|
IPR_EXC_SUM,
|
||||||
|
IPR_EXC_MASK,
|
||||||
|
IPR_PAL_BASE,
|
||||||
|
IPR_ICM,
|
||||||
|
IPR_IPLR,
|
||||||
|
IPR_IFAULT_VA_FORM,
|
||||||
|
IPR_IVPTBR,
|
||||||
|
IPR_ICSR,
|
||||||
|
IPR_IC_PERR_STAT,
|
||||||
|
IPR_PMCTR,
|
||||||
|
|
||||||
|
// PAL temporary registers...
|
||||||
|
// register meanings gleaned from osfpal.s source code
|
||||||
|
IPR_PALtemp0,
|
||||||
|
IPR_PALtemp1,
|
||||||
|
IPR_PALtemp2,
|
||||||
|
IPR_PALtemp3,
|
||||||
|
IPR_PALtemp4,
|
||||||
|
IPR_PALtemp5,
|
||||||
|
IPR_PALtemp6,
|
||||||
|
IPR_PALtemp7,
|
||||||
|
IPR_PALtemp8,
|
||||||
|
IPR_PALtemp9,
|
||||||
|
IPR_PALtemp10,
|
||||||
|
IPR_PALtemp11,
|
||||||
|
IPR_PALtemp12,
|
||||||
|
IPR_PALtemp13,
|
||||||
|
IPR_PALtemp14,
|
||||||
|
IPR_PALtemp15,
|
||||||
|
IPR_PALtemp16,
|
||||||
|
IPR_PALtemp17,
|
||||||
|
IPR_PALtemp18,
|
||||||
|
IPR_PALtemp19,
|
||||||
|
IPR_PALtemp20,
|
||||||
|
IPR_PALtemp21,
|
||||||
|
IPR_PALtemp22,
|
||||||
|
IPR_PALtemp23,
|
||||||
|
|
||||||
|
IPR_DTB_ASN,
|
||||||
|
IPR_DTB_CM,
|
||||||
|
IPR_DTB_TAG,
|
||||||
|
IPR_DTB_PTE,
|
||||||
|
|
||||||
|
IPR_VA,
|
||||||
|
IPR_VA_FORM,
|
||||||
|
IPR_MVPTBR,
|
||||||
|
IPR_DTB_IS,
|
||||||
|
IPR_CC,
|
||||||
|
IPR_CC_CTL,
|
||||||
|
IPR_MCSR,
|
||||||
|
|
||||||
|
IPR_DC_PERR_STAT,
|
||||||
|
IPR_DC_TEST_CTL,
|
||||||
|
IPR_DC_TEST_TAG,
|
||||||
|
IPR_DC_TEST_TAG_TEMP,
|
||||||
|
IPR_DC_MODE,
|
||||||
|
IPR_MAF_MODE,
|
||||||
|
|
||||||
|
NumInternalProcRegs // number of IPR registers
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool IprIsWritable(int index)
|
||||||
|
{
|
||||||
|
return index < MinReadOnlyIpr || index > MaxReadOnlyIpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IprIsReadable(int index)
|
||||||
|
{
|
||||||
|
return index < MinWriteOnlyIpr || index > MaxWriteOnlyIpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern md_ipr_names MiscRegIndexToIpr[NumInternalProcRegs];
|
||||||
|
extern int IprToMiscRegIndex[MaxInternalProcRegs];
|
||||||
|
|
||||||
|
void initializeIprTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -629,7 +629,7 @@ decode OPCODE default Unknown::unknown() {
|
||||||
/* Rb is a fake dependency so here is a fun way to get
|
/* Rb is a fake dependency so here is a fun way to get
|
||||||
* the parser to understand that.
|
* the parser to understand that.
|
||||||
*/
|
*/
|
||||||
Ra = xc->readMiscRegWithEffect(AlphaISA::IPR_CC, fault) + (Rb & 0);
|
Ra = xc->readMiscRegWithEffect(AlphaISA::IPR_CC) + (Rb & 0);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
Ra = curTick;
|
Ra = curTick;
|
||||||
|
@ -661,12 +661,12 @@ decode OPCODE default Unknown::unknown() {
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
format BasicOperate {
|
format BasicOperate {
|
||||||
0xe000: rc({{
|
0xe000: rc({{
|
||||||
Ra = xc->readIntrFlag();
|
Ra = IntrFlag;
|
||||||
xc->setIntrFlag(0);
|
IntrFlag = 0;
|
||||||
}}, IsNonSpeculative, IsUnverifiable);
|
}}, IsNonSpeculative, IsUnverifiable);
|
||||||
0xf000: rs({{
|
0xf000: rs({{
|
||||||
Ra = xc->readIntrFlag();
|
Ra = IntrFlag;
|
||||||
xc->setIntrFlag(1);
|
IntrFlag = 1;
|
||||||
}}, IsNonSpeculative, IsUnverifiable);
|
}}, IsNonSpeculative, IsUnverifiable);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -681,7 +681,7 @@ decode OPCODE default Unknown::unknown() {
|
||||||
0x00: CallPal::call_pal({{
|
0x00: CallPal::call_pal({{
|
||||||
if (!palValid ||
|
if (!palValid ||
|
||||||
(palPriv
|
(palPriv
|
||||||
&& xc->readMiscRegWithEffect(AlphaISA::IPR_ICM, fault) != AlphaISA::mode_kernel)) {
|
&& xc->readMiscRegWithEffect(AlphaISA::IPR_ICM) != AlphaISA::mode_kernel)) {
|
||||||
// invalid pal function code, or attempt to do privileged
|
// invalid pal function code, or attempt to do privileged
|
||||||
// PAL call in non-kernel mode
|
// PAL call in non-kernel mode
|
||||||
fault = new UnimplementedOpcodeFault;
|
fault = new UnimplementedOpcodeFault;
|
||||||
|
@ -693,7 +693,7 @@ decode OPCODE default Unknown::unknown() {
|
||||||
|
|
||||||
if (dopal) {
|
if (dopal) {
|
||||||
xc->setMiscRegWithEffect(AlphaISA::IPR_EXC_ADDR, NPC);
|
xc->setMiscRegWithEffect(AlphaISA::IPR_EXC_ADDR, NPC);
|
||||||
NPC = xc->readMiscRegWithEffect(AlphaISA::IPR_PAL_BASE, fault) + palOffset;
|
NPC = xc->readMiscRegWithEffect(AlphaISA::IPR_PAL_BASE) + palOffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}, IsNonSpeculative);
|
}}, IsNonSpeculative);
|
||||||
|
@ -745,7 +745,13 @@ decode OPCODE default Unknown::unknown() {
|
||||||
0: OpcdecFault::hw_mfpr();
|
0: OpcdecFault::hw_mfpr();
|
||||||
format HwMoveIPR {
|
format HwMoveIPR {
|
||||||
1: hw_mfpr({{
|
1: hw_mfpr({{
|
||||||
Ra = xc->readMiscRegWithEffect(ipr_index, fault);
|
int miscRegIndex = (ipr_index < MaxInternalProcRegs) ?
|
||||||
|
IprToMiscRegIndex[ipr_index] : -1;
|
||||||
|
if(miscRegIndex < 0 || !IprIsReadable(miscRegIndex) ||
|
||||||
|
miscRegIndex >= NumInternalProcRegs)
|
||||||
|
fault = new UnimplementedOpcodeFault;
|
||||||
|
else
|
||||||
|
Ra = xc->readMiscRegWithEffect(miscRegIndex);
|
||||||
}}, IsIprAccess);
|
}}, IsIprAccess);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -754,7 +760,13 @@ decode OPCODE default Unknown::unknown() {
|
||||||
0: OpcdecFault::hw_mtpr();
|
0: OpcdecFault::hw_mtpr();
|
||||||
format HwMoveIPR {
|
format HwMoveIPR {
|
||||||
1: hw_mtpr({{
|
1: hw_mtpr({{
|
||||||
xc->setMiscRegWithEffect(ipr_index, Ra);
|
int miscRegIndex = (ipr_index < MaxInternalProcRegs) ?
|
||||||
|
IprToMiscRegIndex[ipr_index] : -1;
|
||||||
|
if(miscRegIndex < 0 || !IprIsWritable(miscRegIndex) ||
|
||||||
|
miscRegIndex >= NumInternalProcRegs)
|
||||||
|
fault = new UnimplementedOpcodeFault;
|
||||||
|
else
|
||||||
|
xc->setMiscRegWithEffect(miscRegIndex, Ra);
|
||||||
if (traceData) { traceData->setData(Ra); }
|
if (traceData) { traceData->setData(Ra); }
|
||||||
}}, IsIprAccess);
|
}}, IsIprAccess);
|
||||||
}
|
}
|
||||||
|
@ -783,12 +795,6 @@ decode OPCODE default Unknown::unknown() {
|
||||||
0x04: quiesceTime({{
|
0x04: quiesceTime({{
|
||||||
R0 = AlphaPseudo::quiesceTime(xc->tcBase());
|
R0 = AlphaPseudo::quiesceTime(xc->tcBase());
|
||||||
}}, IsNonSpeculative, IsUnverifiable);
|
}}, IsNonSpeculative, IsUnverifiable);
|
||||||
0x10: ivlb({{
|
|
||||||
AlphaPseudo::ivlb(xc->tcBase());
|
|
||||||
}}, No_OpClass, IsNonSpeculative);
|
|
||||||
0x11: ivle({{
|
|
||||||
AlphaPseudo::ivle(xc->tcBase());
|
|
||||||
}}, No_OpClass, IsNonSpeculative);
|
|
||||||
0x20: m5exit_old({{
|
0x20: m5exit_old({{
|
||||||
AlphaPseudo::m5exit_old(xc->tcBase());
|
AlphaPseudo::m5exit_old(xc->tcBase());
|
||||||
}}, No_OpClass, IsNonSpeculative);
|
}}, No_OpClass, IsNonSpeculative);
|
||||||
|
|
|
@ -46,7 +46,7 @@ output exec {{
|
||||||
inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
|
inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
|
||||||
{
|
{
|
||||||
Fault fault = NoFault; // dummy... this ipr access should not fault
|
Fault fault = NoFault; // dummy... this ipr access should not fault
|
||||||
if (!EV5::ICSR_FPE(xc->readMiscRegWithEffect(AlphaISA::IPR_ICSR, fault))) {
|
if (!EV5::ICSR_FPE(xc->readMiscRegWithEffect(AlphaISA::IPR_ICSR))) {
|
||||||
fault = new FloatEnableFault;
|
fault = new FloatEnableFault;
|
||||||
}
|
}
|
||||||
return fault;
|
return fault;
|
||||||
|
@ -229,7 +229,7 @@ def template FloatingPointExecute {{
|
||||||
%(code)s;
|
%(code)s;
|
||||||
} else {
|
} else {
|
||||||
fesetround(getC99RoundingMode(
|
fesetround(getC99RoundingMode(
|
||||||
xc->readMiscReg(AlphaISA::Fpcr_DepTag)));
|
xc->readMiscReg(AlphaISA::MISCREG_FPCR)));
|
||||||
%(code)s;
|
%(code)s;
|
||||||
fesetround(FE_TONEAREST);
|
fesetround(FE_TONEAREST);
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,6 +71,7 @@ output exec {{
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
#include "sim/pseudo_inst.hh"
|
#include "sim/pseudo_inst.hh"
|
||||||
#endif
|
#endif
|
||||||
|
#include "arch/alpha/ipr.hh"
|
||||||
#include "base/fenv.hh"
|
#include "base/fenv.hh"
|
||||||
#include "config/ss_compatible_fp.hh"
|
#include "config/ss_compatible_fp.hh"
|
||||||
#include "cpu/base.hh"
|
#include "cpu/base.hh"
|
||||||
|
@ -183,8 +184,9 @@ def operands {{
|
||||||
'Fc': ('FloatReg', 'df', 'FC', 'IsFloating', 3),
|
'Fc': ('FloatReg', 'df', 'FC', 'IsFloating', 3),
|
||||||
'Mem': ('Mem', 'uq', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4),
|
'Mem': ('Mem', 'uq', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4),
|
||||||
'NPC': ('NPC', 'uq', None, ( None, None, 'IsControl' ), 4),
|
'NPC': ('NPC', 'uq', None, ( None, None, 'IsControl' ), 4),
|
||||||
'Runiq': ('ControlReg', 'uq', 'TheISA::Uniq_DepTag', None, 1),
|
'Runiq': ('ControlReg', 'uq', 'MISCREG_UNIQ', None, 1),
|
||||||
'FPCR': (' ControlReg', 'uq', 'TheISA::Fpcr_DepTag', None, 1),
|
'FPCR': ('ControlReg', 'uq', 'MISCREG_FPCR', None, 1),
|
||||||
|
'IntrFlag': ('ControlReg', 'uq', 'MISCREG_INTR', None, 1),
|
||||||
# The next two are hacks for non-full-system call-pal emulation
|
# The next two are hacks for non-full-system call-pal emulation
|
||||||
'R0': ('IntReg', 'uq', '0', None, 1),
|
'R0': ('IntReg', 'uq', '0', None, 1),
|
||||||
'R16': ('IntReg', 'uq', '16', None, 1),
|
'R16': ('IntReg', 'uq', '16', None, 1),
|
||||||
|
@ -214,11 +216,6 @@ output header {{
|
||||||
/// live here and not in the AlphaISA namespace.
|
/// live here and not in the AlphaISA namespace.
|
||||||
enum DependenceTags {
|
enum DependenceTags {
|
||||||
FP_Base_DepTag = AlphaISA::FP_Base_DepTag,
|
FP_Base_DepTag = AlphaISA::FP_Base_DepTag,
|
||||||
Fpcr_DepTag = AlphaISA::Fpcr_DepTag,
|
|
||||||
Uniq_DepTag = AlphaISA::Uniq_DepTag,
|
|
||||||
Lock_Flag_DepTag = AlphaISA::Lock_Flag_DepTag,
|
|
||||||
Lock_Addr_DepTag = AlphaISA::Lock_Addr_DepTag,
|
|
||||||
IPR_Base_DepTag = AlphaISA::IPR_Base_DepTag
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Constructor.
|
/// Constructor.
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
|
|
||||||
namespace LittleEndianGuest {}
|
namespace LittleEndianGuest {}
|
||||||
|
|
||||||
|
#include "arch/alpha/ipr.hh"
|
||||||
#include "arch/alpha/types.hh"
|
#include "arch/alpha/types.hh"
|
||||||
#include "config/full_system.hh"
|
#include "config/full_system.hh"
|
||||||
#include "sim/host.hh"
|
#include "sim/host.hh"
|
||||||
|
@ -49,12 +50,7 @@ namespace AlphaISA
|
||||||
// 0..31 are the integer regs 0..31
|
// 0..31 are the integer regs 0..31
|
||||||
// 32..63 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag)
|
// 32..63 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag)
|
||||||
FP_Base_DepTag = 40,
|
FP_Base_DepTag = 40,
|
||||||
Ctrl_Base_DepTag = 72,
|
Ctrl_Base_DepTag = 72
|
||||||
Fpcr_DepTag = 72, // floating point control register
|
|
||||||
Uniq_DepTag = 73,
|
|
||||||
Lock_Flag_DepTag = 74,
|
|
||||||
Lock_Addr_DepTag = 75,
|
|
||||||
IPR_Base_DepTag = 76
|
|
||||||
};
|
};
|
||||||
|
|
||||||
StaticInstPtr decodeInst(ExtMachInst);
|
StaticInstPtr decodeInst(ExtMachInst);
|
||||||
|
@ -118,7 +114,6 @@ namespace AlphaISA
|
||||||
NumInterruptLevels = INTLEVEL_EXTERNAL_MAX
|
NumInterruptLevels = INTLEVEL_EXTERNAL_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// EV5 modes
|
// EV5 modes
|
||||||
enum mode_type
|
enum mode_type
|
||||||
{
|
{
|
||||||
|
@ -131,100 +126,6 @@ namespace AlphaISA
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Internal Processor Reigsters
|
|
||||||
//
|
|
||||||
enum md_ipr_names
|
|
||||||
{
|
|
||||||
IPR_ISR = 0x100, // interrupt summary register
|
|
||||||
IPR_ITB_TAG = 0x101, // ITLB tag register
|
|
||||||
IPR_ITB_PTE = 0x102, // ITLB page table entry register
|
|
||||||
IPR_ITB_ASN = 0x103, // ITLB address space register
|
|
||||||
IPR_ITB_PTE_TEMP = 0x104, // ITLB page table entry temp register
|
|
||||||
IPR_ITB_IA = 0x105, // ITLB invalidate all register
|
|
||||||
IPR_ITB_IAP = 0x106, // ITLB invalidate all process register
|
|
||||||
IPR_ITB_IS = 0x107, // ITLB invalidate select register
|
|
||||||
IPR_SIRR = 0x108, // software interrupt request register
|
|
||||||
IPR_ASTRR = 0x109, // asynchronous system trap request register
|
|
||||||
IPR_ASTER = 0x10a, // asynchronous system trap enable register
|
|
||||||
IPR_EXC_ADDR = 0x10b, // exception address register
|
|
||||||
IPR_EXC_SUM = 0x10c, // exception summary register
|
|
||||||
IPR_EXC_MASK = 0x10d, // exception mask register
|
|
||||||
IPR_PAL_BASE = 0x10e, // PAL base address register
|
|
||||||
IPR_ICM = 0x10f, // instruction current mode
|
|
||||||
IPR_IPLR = 0x110, // interrupt priority level register
|
|
||||||
IPR_INTID = 0x111, // interrupt ID register
|
|
||||||
IPR_IFAULT_VA_FORM = 0x112, // formatted faulting virtual addr register
|
|
||||||
IPR_IVPTBR = 0x113, // virtual page table base register
|
|
||||||
IPR_HWINT_CLR = 0x115, // H/W interrupt clear register
|
|
||||||
IPR_SL_XMIT = 0x116, // serial line transmit register
|
|
||||||
IPR_SL_RCV = 0x117, // serial line receive register
|
|
||||||
IPR_ICSR = 0x118, // instruction control and status register
|
|
||||||
IPR_IC_FLUSH = 0x119, // instruction cache flush control
|
|
||||||
IPR_IC_PERR_STAT = 0x11a, // inst cache parity error status register
|
|
||||||
IPR_PMCTR = 0x11c, // performance counter register
|
|
||||||
|
|
||||||
// PAL temporary registers...
|
|
||||||
// register meanings gleaned from osfpal.s source code
|
|
||||||
IPR_PALtemp0 = 0x140, // local scratch
|
|
||||||
IPR_PALtemp1 = 0x141, // local scratch
|
|
||||||
IPR_PALtemp2 = 0x142, // entUna
|
|
||||||
IPR_PALtemp3 = 0x143, // CPU specific impure area pointer
|
|
||||||
IPR_PALtemp4 = 0x144, // memory management temp
|
|
||||||
IPR_PALtemp5 = 0x145, // memory management temp
|
|
||||||
IPR_PALtemp6 = 0x146, // memory management temp
|
|
||||||
IPR_PALtemp7 = 0x147, // entIF
|
|
||||||
IPR_PALtemp8 = 0x148, // intmask
|
|
||||||
IPR_PALtemp9 = 0x149, // entSys
|
|
||||||
IPR_PALtemp10 = 0x14a, // ??
|
|
||||||
IPR_PALtemp11 = 0x14b, // entInt
|
|
||||||
IPR_PALtemp12 = 0x14c, // entArith
|
|
||||||
IPR_PALtemp13 = 0x14d, // reserved for platform specific PAL
|
|
||||||
IPR_PALtemp14 = 0x14e, // reserved for platform specific PAL
|
|
||||||
IPR_PALtemp15 = 0x14f, // reserved for platform specific PAL
|
|
||||||
IPR_PALtemp16 = 0x150, // scratch / whami<7:0> / mces<4:0>
|
|
||||||
IPR_PALtemp17 = 0x151, // sysval
|
|
||||||
IPR_PALtemp18 = 0x152, // usp
|
|
||||||
IPR_PALtemp19 = 0x153, // ksp
|
|
||||||
IPR_PALtemp20 = 0x154, // PTBR
|
|
||||||
IPR_PALtemp21 = 0x155, // entMM
|
|
||||||
IPR_PALtemp22 = 0x156, // kgp
|
|
||||||
IPR_PALtemp23 = 0x157, // PCBB
|
|
||||||
|
|
||||||
IPR_DTB_ASN = 0x200, // DTLB address space number register
|
|
||||||
IPR_DTB_CM = 0x201, // DTLB current mode register
|
|
||||||
IPR_DTB_TAG = 0x202, // DTLB tag register
|
|
||||||
IPR_DTB_PTE = 0x203, // DTLB page table entry register
|
|
||||||
IPR_DTB_PTE_TEMP = 0x204, // DTLB page table entry temporary register
|
|
||||||
|
|
||||||
IPR_MM_STAT = 0x205, // data MMU fault status register
|
|
||||||
IPR_VA = 0x206, // fault virtual address register
|
|
||||||
IPR_VA_FORM = 0x207, // formatted virtual address register
|
|
||||||
IPR_MVPTBR = 0x208, // MTU virtual page table base register
|
|
||||||
IPR_DTB_IAP = 0x209, // DTLB invalidate all process register
|
|
||||||
IPR_DTB_IA = 0x20a, // DTLB invalidate all register
|
|
||||||
IPR_DTB_IS = 0x20b, // DTLB invalidate single register
|
|
||||||
IPR_ALT_MODE = 0x20c, // alternate mode register
|
|
||||||
IPR_CC = 0x20d, // cycle counter register
|
|
||||||
IPR_CC_CTL = 0x20e, // cycle counter control register
|
|
||||||
IPR_MCSR = 0x20f, // MTU control register
|
|
||||||
|
|
||||||
IPR_DC_FLUSH = 0x210,
|
|
||||||
IPR_DC_PERR_STAT = 0x212, // Dcache parity error status register
|
|
||||||
IPR_DC_TEST_CTL = 0x213, // Dcache test tag control register
|
|
||||||
IPR_DC_TEST_TAG = 0x214, // Dcache test tag register
|
|
||||||
IPR_DC_TEST_TAG_TEMP = 0x215, // Dcache test tag temporary register
|
|
||||||
IPR_DC_MODE = 0x216, // Dcache mode register
|
|
||||||
IPR_MAF_MODE = 0x217, // miss address file mode register
|
|
||||||
|
|
||||||
NumInternalProcRegs // number of IPR registers
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
const int NumInternalProcRegs = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Constants Related to the number of registers
|
// Constants Related to the number of registers
|
||||||
|
|
||||||
const int NumIntArchRegs = 32;
|
const int NumIntArchRegs = 32;
|
||||||
|
@ -279,9 +180,6 @@ namespace AlphaISA
|
||||||
// Alpha UNOP (ldq_u r31,0(r0))
|
// Alpha UNOP (ldq_u r31,0(r0))
|
||||||
const ExtMachInst NoopMachInst = 0x2ffe0000;
|
const ExtMachInst NoopMachInst = 0x2ffe0000;
|
||||||
|
|
||||||
// redirected register map, really only used for the full system case.
|
|
||||||
extern const int reg_redir[NumIntRegs];
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __ARCH_ALPHA_ISA_TRAITS_HH__
|
#endif // __ARCH_ALPHA_ISA_TRAITS_HH__
|
||||||
|
|
211
src/arch/alpha/kernel_stats.cc
Normal file
211
src/arch/alpha/kernel_stats.cc
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2004-2005 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Lisa Hsu
|
||||||
|
* Nathan Binkert
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <stack>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "arch/alpha/kernel_stats.hh"
|
||||||
|
#include "arch/alpha/osfpal.hh"
|
||||||
|
#include "base/trace.hh"
|
||||||
|
#include "cpu/thread_context.hh"
|
||||||
|
#include "kern/tru64/tru64_syscalls.hh"
|
||||||
|
#include "sim/system.hh"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace Stats;
|
||||||
|
|
||||||
|
namespace AlphaISA {
|
||||||
|
namespace Kernel {
|
||||||
|
|
||||||
|
const char *modestr[] = { "kernel", "user", "idle" };
|
||||||
|
|
||||||
|
Statistics::Statistics(System *system)
|
||||||
|
: ::Kernel::Statistics(system),
|
||||||
|
idleProcess((Addr)-1), themode(kernel), lastModeTick(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Statistics::regStats(const string &_name)
|
||||||
|
{
|
||||||
|
::Kernel::Statistics::regStats(_name);
|
||||||
|
|
||||||
|
_callpal
|
||||||
|
.init(256)
|
||||||
|
.name(name() + ".callpal")
|
||||||
|
.desc("number of callpals executed")
|
||||||
|
.flags(total | pdf | nozero | nonan)
|
||||||
|
;
|
||||||
|
|
||||||
|
for (int i = 0; i < PAL::NumCodes; ++i) {
|
||||||
|
const char *str = PAL::name(i);
|
||||||
|
if (str)
|
||||||
|
_callpal.subname(i, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
_hwrei
|
||||||
|
.name(name() + ".inst.hwrei")
|
||||||
|
.desc("number of hwrei instructions executed")
|
||||||
|
;
|
||||||
|
|
||||||
|
_mode
|
||||||
|
.init(cpu_mode_num)
|
||||||
|
.name(name() + ".mode_switch")
|
||||||
|
.desc("number of protection mode switches")
|
||||||
|
;
|
||||||
|
|
||||||
|
for (int i = 0; i < cpu_mode_num; ++i)
|
||||||
|
_mode.subname(i, modestr[i]);
|
||||||
|
|
||||||
|
_modeGood
|
||||||
|
.init(cpu_mode_num)
|
||||||
|
.name(name() + ".mode_good")
|
||||||
|
;
|
||||||
|
|
||||||
|
for (int i = 0; i < cpu_mode_num; ++i)
|
||||||
|
_modeGood.subname(i, modestr[i]);
|
||||||
|
|
||||||
|
_modeFraction
|
||||||
|
.name(name() + ".mode_switch_good")
|
||||||
|
.desc("fraction of useful protection mode switches")
|
||||||
|
.flags(total)
|
||||||
|
;
|
||||||
|
|
||||||
|
for (int i = 0; i < cpu_mode_num; ++i)
|
||||||
|
_modeFraction.subname(i, modestr[i]);
|
||||||
|
|
||||||
|
_modeFraction = _modeGood / _mode;
|
||||||
|
|
||||||
|
_modeTicks
|
||||||
|
.init(cpu_mode_num)
|
||||||
|
.name(name() + ".mode_ticks")
|
||||||
|
.desc("number of ticks spent at the given mode")
|
||||||
|
.flags(pdf)
|
||||||
|
;
|
||||||
|
for (int i = 0; i < cpu_mode_num; ++i)
|
||||||
|
_modeTicks.subname(i, modestr[i]);
|
||||||
|
|
||||||
|
_swap_context
|
||||||
|
.name(name() + ".swap_context")
|
||||||
|
.desc("number of times the context was actually changed")
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Statistics::setIdleProcess(Addr idlepcbb, ThreadContext *tc)
|
||||||
|
{
|
||||||
|
assert(themode == kernel);
|
||||||
|
idleProcess = idlepcbb;
|
||||||
|
themode = idle;
|
||||||
|
changeMode(themode, tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Statistics::changeMode(cpu_mode newmode, ThreadContext *tc)
|
||||||
|
{
|
||||||
|
_mode[newmode]++;
|
||||||
|
|
||||||
|
if (newmode == themode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DPRINTF(Context, "old mode=%-8s new mode=%-8s\n",
|
||||||
|
modestr[themode], modestr[newmode]);
|
||||||
|
|
||||||
|
_modeGood[newmode]++;
|
||||||
|
_modeTicks[themode] += curTick - lastModeTick;
|
||||||
|
|
||||||
|
lastModeTick = curTick;
|
||||||
|
themode = newmode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Statistics::mode(cpu_mode newmode, ThreadContext *tc)
|
||||||
|
{
|
||||||
|
Addr pcbb = tc->readMiscReg(AlphaISA::IPR_PALtemp23);
|
||||||
|
|
||||||
|
if (newmode == kernel && pcbb == idleProcess)
|
||||||
|
newmode = idle;
|
||||||
|
|
||||||
|
changeMode(newmode, tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Statistics::context(Addr oldpcbb, Addr newpcbb, ThreadContext *tc)
|
||||||
|
{
|
||||||
|
assert(themode != user);
|
||||||
|
|
||||||
|
_swap_context++;
|
||||||
|
changeMode(newpcbb == idleProcess ? idle : kernel, tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Statistics::callpal(int code, ThreadContext *tc)
|
||||||
|
{
|
||||||
|
if (!PAL::name(code))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_callpal[code]++;
|
||||||
|
|
||||||
|
switch (code) {
|
||||||
|
case PAL::callsys: {
|
||||||
|
int number = tc->readIntReg(0);
|
||||||
|
if (SystemCalls<Tru64>::validSyscallNumber(number)) {
|
||||||
|
int cvtnum = SystemCalls<Tru64>::convert(number);
|
||||||
|
_syscall[cvtnum]++;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Statistics::serialize(ostream &os)
|
||||||
|
{
|
||||||
|
::Kernel::Statistics::serialize(os);
|
||||||
|
int exemode = themode;
|
||||||
|
SERIALIZE_SCALAR(exemode);
|
||||||
|
SERIALIZE_SCALAR(idleProcess);
|
||||||
|
SERIALIZE_SCALAR(lastModeTick);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Statistics::unserialize(Checkpoint *cp, const string §ion)
|
||||||
|
{
|
||||||
|
::Kernel::Statistics::unserialize(cp, section);
|
||||||
|
int exemode;
|
||||||
|
UNSERIALIZE_SCALAR(exemode);
|
||||||
|
UNSERIALIZE_SCALAR(idleProcess);
|
||||||
|
UNSERIALIZE_SCALAR(lastModeTick);
|
||||||
|
themode = (cpu_mode)exemode;
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* end namespace AlphaISA::Kernel */
|
||||||
|
} /* end namespace AlphaISA */
|
96
src/arch/alpha/kernel_stats.hh
Normal file
96
src/arch/alpha/kernel_stats.hh
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2004-2005 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Lisa Hsu
|
||||||
|
* Nathan Binkert
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ARCH_ALPHA_KERNEL_STATS_HH__
|
||||||
|
#define __ARCH_ALPHA_KERNEL_STATS_HH__
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <stack>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "cpu/static_inst.hh"
|
||||||
|
#include "kern/kernel_stats.hh"
|
||||||
|
|
||||||
|
class BaseCPU;
|
||||||
|
class ThreadContext;
|
||||||
|
class FnEvent;
|
||||||
|
// What does kernel stats expect is included?
|
||||||
|
class System;
|
||||||
|
|
||||||
|
namespace AlphaISA {
|
||||||
|
namespace Kernel {
|
||||||
|
|
||||||
|
enum cpu_mode { kernel, user, idle, cpu_mode_num };
|
||||||
|
extern const char *modestr[];
|
||||||
|
|
||||||
|
class Statistics : public ::Kernel::Statistics
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
Addr idleProcess;
|
||||||
|
cpu_mode themode;
|
||||||
|
Tick lastModeTick;
|
||||||
|
|
||||||
|
void changeMode(cpu_mode newmode, ThreadContext *tc);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Stats::Vector<> _callpal;
|
||||||
|
// Stats::Vector<> _faults;
|
||||||
|
|
||||||
|
Stats::Vector<> _mode;
|
||||||
|
Stats::Vector<> _modeGood;
|
||||||
|
Stats::Formula _modeFraction;
|
||||||
|
Stats::Vector<> _modeTicks;
|
||||||
|
|
||||||
|
Stats::Scalar<> _swap_context;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Statistics(System *system);
|
||||||
|
|
||||||
|
void regStats(const std::string &name);
|
||||||
|
|
||||||
|
public:
|
||||||
|
void mode(cpu_mode newmode, ThreadContext *tc);
|
||||||
|
void context(Addr oldpcbb, Addr newpcbb, ThreadContext *tc);
|
||||||
|
void callpal(int code, ThreadContext *tc);
|
||||||
|
void hwrei() { _hwrei++; }
|
||||||
|
|
||||||
|
void setIdleProcess(Addr idle, ThreadContext *tc);
|
||||||
|
|
||||||
|
public:
|
||||||
|
void serialize(std::ostream &os);
|
||||||
|
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* end namespace AlphaISA::Kernel */
|
||||||
|
} /* end namespace AlphaISA */
|
||||||
|
|
||||||
|
#endif // __ARCH_ALPHA_KERNEL_STATS_HH__
|
|
@ -160,15 +160,4 @@
|
||||||
/* Too much? Must be large enough for register transfer. */
|
/* Too much? Must be large enough for register transfer. */
|
||||||
#define KGDB_BUFLEN 1024
|
#define KGDB_BUFLEN 1024
|
||||||
|
|
||||||
/*
|
|
||||||
* Kernel Entry Vectors. [OSF/1 PALcode Specific]
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define ALPHA_KENTRY_INT 0
|
|
||||||
#define ALPHA_KENTRY_ARITH 1
|
|
||||||
#define ALPHA_KENTRY_MM 2
|
|
||||||
#define ALPHA_KENTRY_IF 3
|
|
||||||
#define ALPHA_KENTRY_UNA 4
|
|
||||||
#define ALPHA_KENTRY_SYS 5
|
|
||||||
|
|
||||||
#endif /* __KGDB_H__ */
|
#endif /* __KGDB_H__ */
|
|
@ -42,6 +42,7 @@
|
||||||
|
|
||||||
#include "arch/arguments.hh"
|
#include "arch/arguments.hh"
|
||||||
#include "arch/vtophys.hh"
|
#include "arch/vtophys.hh"
|
||||||
|
#include "arch/alpha/idle_event.hh"
|
||||||
#include "arch/alpha/linux/system.hh"
|
#include "arch/alpha/linux/system.hh"
|
||||||
#include "arch/alpha/linux/threadinfo.hh"
|
#include "arch/alpha/linux/threadinfo.hh"
|
||||||
#include "arch/alpha/system.hh"
|
#include "arch/alpha/system.hh"
|
||||||
|
|
|
@ -38,6 +38,7 @@ class ThreadContext;
|
||||||
class BreakPCEvent;
|
class BreakPCEvent;
|
||||||
class IdleStartEvent;
|
class IdleStartEvent;
|
||||||
|
|
||||||
|
#include "arch/alpha/idle_event.hh"
|
||||||
#include "arch/alpha/system.hh"
|
#include "arch/alpha/system.hh"
|
||||||
#include "kern/linux/events.hh"
|
#include "kern/linux/events.hh"
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
* ISA-specific helper functions for locked memory accesses.
|
* ISA-specific helper functions for locked memory accesses.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "arch/isa_traits.hh"
|
#include "arch/alpha/miscregfile.hh"
|
||||||
#include "base/misc.hh"
|
#include "base/misc.hh"
|
||||||
#include "mem/request.hh"
|
#include "mem/request.hh"
|
||||||
|
|
||||||
|
@ -48,8 +48,8 @@ template <class XC>
|
||||||
inline void
|
inline void
|
||||||
handleLockedRead(XC *xc, Request *req)
|
handleLockedRead(XC *xc, Request *req)
|
||||||
{
|
{
|
||||||
xc->setMiscReg(Lock_Addr_DepTag, req->getPaddr() & ~0xf);
|
xc->setMiscReg(MISCREG_LOCKADDR, req->getPaddr() & ~0xf);
|
||||||
xc->setMiscReg(Lock_Flag_DepTag, true);
|
xc->setMiscReg(MISCREG_LOCKFLAG, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -63,13 +63,13 @@ handleLockedWrite(XC *xc, Request *req)
|
||||||
req->setScResult(2);
|
req->setScResult(2);
|
||||||
} else {
|
} else {
|
||||||
// standard store conditional
|
// standard store conditional
|
||||||
bool lock_flag = xc->readMiscReg(Lock_Flag_DepTag);
|
bool lock_flag = xc->readMiscReg(MISCREG_LOCKFLAG);
|
||||||
Addr lock_addr = xc->readMiscReg(Lock_Addr_DepTag);
|
Addr lock_addr = xc->readMiscReg(MISCREG_LOCKADDR);
|
||||||
if (!lock_flag || (req->getPaddr() & ~0xf) != lock_addr) {
|
if (!lock_flag || (req->getPaddr() & ~0xf) != lock_addr) {
|
||||||
// Lock flag not set or addr mismatch in CPU;
|
// Lock flag not set or addr mismatch in CPU;
|
||||||
// don't even bother sending to memory system
|
// don't even bother sending to memory system
|
||||||
req->setScResult(0);
|
req->setScResult(0);
|
||||||
xc->setMiscReg(Lock_Flag_DepTag, false);
|
xc->setMiscReg(MISCREG_LOCKFLAG, false);
|
||||||
// the rest of this code is not architectural;
|
// the rest of this code is not architectural;
|
||||||
// it's just a debugging aid to help detect
|
// it's just a debugging aid to help detect
|
||||||
// livelock by warning on long sequences of failed
|
// livelock by warning on long sequences of failed
|
||||||
|
|
161
src/arch/alpha/miscregfile.cc
Normal file
161
src/arch/alpha/miscregfile.cc
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003-2005 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Steve Reinhardt
|
||||||
|
* Gabe Black
|
||||||
|
* Kevin Lim
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "arch/alpha/miscregfile.hh"
|
||||||
|
#include "base/misc.hh"
|
||||||
|
|
||||||
|
namespace AlphaISA
|
||||||
|
{
|
||||||
|
|
||||||
|
void
|
||||||
|
MiscRegFile::serialize(std::ostream &os)
|
||||||
|
{
|
||||||
|
SERIALIZE_SCALAR(fpcr);
|
||||||
|
SERIALIZE_SCALAR(uniq);
|
||||||
|
SERIALIZE_SCALAR(lock_flag);
|
||||||
|
SERIALIZE_SCALAR(lock_addr);
|
||||||
|
#if FULL_SYSTEM
|
||||||
|
SERIALIZE_ARRAY(ipr, NumInternalProcRegs);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MiscRegFile::unserialize(Checkpoint *cp, const std::string §ion)
|
||||||
|
{
|
||||||
|
UNSERIALIZE_SCALAR(fpcr);
|
||||||
|
UNSERIALIZE_SCALAR(uniq);
|
||||||
|
UNSERIALIZE_SCALAR(lock_flag);
|
||||||
|
UNSERIALIZE_SCALAR(lock_addr);
|
||||||
|
#if FULL_SYSTEM
|
||||||
|
UNSERIALIZE_ARRAY(ipr, NumInternalProcRegs);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
MiscReg
|
||||||
|
MiscRegFile::readReg(int misc_reg)
|
||||||
|
{
|
||||||
|
switch(misc_reg) {
|
||||||
|
case MISCREG_FPCR:
|
||||||
|
return fpcr;
|
||||||
|
case MISCREG_UNIQ:
|
||||||
|
return uniq;
|
||||||
|
case MISCREG_LOCKFLAG:
|
||||||
|
return lock_flag;
|
||||||
|
case MISCREG_LOCKADDR:
|
||||||
|
return lock_addr;
|
||||||
|
case MISCREG_INTR:
|
||||||
|
return intr_flag;
|
||||||
|
#if FULL_SYSTEM
|
||||||
|
default:
|
||||||
|
assert(misc_reg < NumInternalProcRegs);
|
||||||
|
return ipr[misc_reg];
|
||||||
|
#else
|
||||||
|
default:
|
||||||
|
panic("Attempt to read an invalid misc register!");
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MiscReg
|
||||||
|
MiscRegFile::readRegWithEffect(int misc_reg, ThreadContext *tc)
|
||||||
|
{
|
||||||
|
#if FULL_SYSTEM
|
||||||
|
return readIpr(misc_reg, tc);
|
||||||
|
#else
|
||||||
|
panic("No faulting misc regs in SE mode!");
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MiscRegFile::setReg(int misc_reg, const MiscReg &val)
|
||||||
|
{
|
||||||
|
switch(misc_reg) {
|
||||||
|
case MISCREG_FPCR:
|
||||||
|
fpcr = val;
|
||||||
|
return;
|
||||||
|
case MISCREG_UNIQ:
|
||||||
|
uniq = val;
|
||||||
|
return;
|
||||||
|
case MISCREG_LOCKFLAG:
|
||||||
|
lock_flag = val;
|
||||||
|
return;
|
||||||
|
case MISCREG_LOCKADDR:
|
||||||
|
lock_addr = val;
|
||||||
|
return;
|
||||||
|
case MISCREG_INTR:
|
||||||
|
intr_flag = val;
|
||||||
|
return;
|
||||||
|
#if FULL_SYSTEM
|
||||||
|
default:
|
||||||
|
assert(misc_reg < NumInternalProcRegs);
|
||||||
|
ipr[misc_reg] = val;
|
||||||
|
return;
|
||||||
|
#else
|
||||||
|
default:
|
||||||
|
panic("Attempt to write to an invalid misc register!");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MiscRegFile::setRegWithEffect(int misc_reg, const MiscReg &val,
|
||||||
|
ThreadContext *tc)
|
||||||
|
{
|
||||||
|
#if FULL_SYSTEM
|
||||||
|
switch(misc_reg) {
|
||||||
|
case MISCREG_FPCR:
|
||||||
|
fpcr = val;
|
||||||
|
return;
|
||||||
|
case MISCREG_UNIQ:
|
||||||
|
uniq = val;
|
||||||
|
return;
|
||||||
|
case MISCREG_LOCKFLAG:
|
||||||
|
lock_flag = val;
|
||||||
|
return;
|
||||||
|
case MISCREG_LOCKADDR:
|
||||||
|
lock_addr = val;
|
||||||
|
return;
|
||||||
|
case MISCREG_INTR:
|
||||||
|
intr_flag = val;
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
return setIpr(misc_reg, val, tc);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
//panic("No registers with side effects in SE mode!");
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
123
src/arch/alpha/miscregfile.hh
Normal file
123
src/arch/alpha/miscregfile.hh
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003-2005 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Steve Reinhardt
|
||||||
|
* Gabe Black
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ARCH_ALPHA_MISCREGFILE_HH__
|
||||||
|
#define __ARCH_ALPHA_MISCREGFILE_HH__
|
||||||
|
|
||||||
|
#include "arch/alpha/ipr.hh"
|
||||||
|
#include "arch/alpha/types.hh"
|
||||||
|
#include "config/full_system.hh"
|
||||||
|
#include "sim/host.hh"
|
||||||
|
#include "sim/serialize.hh"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
class Checkpoint;
|
||||||
|
class ThreadContext;
|
||||||
|
|
||||||
|
namespace AlphaISA
|
||||||
|
{
|
||||||
|
enum MiscRegIndex
|
||||||
|
{
|
||||||
|
MISCREG_FPCR = NumInternalProcRegs,
|
||||||
|
MISCREG_UNIQ,
|
||||||
|
MISCREG_LOCKFLAG,
|
||||||
|
MISCREG_LOCKADDR,
|
||||||
|
MISCREG_INTR
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline std::string getMiscRegName(RegIndex)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
class MiscRegFile {
|
||||||
|
protected:
|
||||||
|
uint64_t fpcr; // floating point condition codes
|
||||||
|
uint64_t uniq; // process-unique register
|
||||||
|
bool lock_flag; // lock flag for LL/SC
|
||||||
|
Addr lock_addr; // lock address for LL/SC
|
||||||
|
int intr_flag;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MiscRegFile()
|
||||||
|
{
|
||||||
|
#if FULL_SYSTEM
|
||||||
|
initializeIprTable();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
MiscReg readReg(int misc_reg);
|
||||||
|
|
||||||
|
MiscReg readRegWithEffect(int misc_reg, ThreadContext *tc);
|
||||||
|
|
||||||
|
//These functions should be removed once the simplescalar cpu model
|
||||||
|
//has been replaced.
|
||||||
|
int getInstAsid();
|
||||||
|
int getDataAsid();
|
||||||
|
|
||||||
|
void setReg(int misc_reg, const MiscReg &val);
|
||||||
|
|
||||||
|
void setRegWithEffect(int misc_reg, const MiscReg &val,
|
||||||
|
ThreadContext *tc);
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
fpcr = uniq = 0;
|
||||||
|
lock_flag = 0;
|
||||||
|
lock_addr = 0;
|
||||||
|
intr_flag = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serialize(std::ostream &os);
|
||||||
|
|
||||||
|
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||||
|
#if FULL_SYSTEM
|
||||||
|
protected:
|
||||||
|
typedef uint64_t InternalProcReg;
|
||||||
|
|
||||||
|
InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs
|
||||||
|
|
||||||
|
private:
|
||||||
|
InternalProcReg readIpr(int idx, ThreadContext *tc);
|
||||||
|
|
||||||
|
void setIpr(int idx, InternalProcReg val, ThreadContext *tc);
|
||||||
|
#endif
|
||||||
|
friend class RegFile;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if FULL_SYSTEM
|
||||||
|
void copyIprs(ThreadContext *src, ThreadContext *dest);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
63
src/arch/alpha/pagetable.cc
Normal file
63
src/arch/alpha/pagetable.cc
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Gabe Black
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "arch/alpha/pagetable.hh"
|
||||||
|
#include "sim/serialize.hh"
|
||||||
|
|
||||||
|
namespace AlphaISA
|
||||||
|
{
|
||||||
|
void
|
||||||
|
PTE::serialize(std::ostream &os)
|
||||||
|
{
|
||||||
|
SERIALIZE_SCALAR(tag);
|
||||||
|
SERIALIZE_SCALAR(ppn);
|
||||||
|
SERIALIZE_SCALAR(xre);
|
||||||
|
SERIALIZE_SCALAR(xwe);
|
||||||
|
SERIALIZE_SCALAR(asn);
|
||||||
|
SERIALIZE_SCALAR(asma);
|
||||||
|
SERIALIZE_SCALAR(fonr);
|
||||||
|
SERIALIZE_SCALAR(fonw);
|
||||||
|
SERIALIZE_SCALAR(valid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PTE::unserialize(Checkpoint *cp, const std::string §ion)
|
||||||
|
{
|
||||||
|
UNSERIALIZE_SCALAR(tag);
|
||||||
|
UNSERIALIZE_SCALAR(ppn);
|
||||||
|
UNSERIALIZE_SCALAR(xre);
|
||||||
|
UNSERIALIZE_SCALAR(xwe);
|
||||||
|
UNSERIALIZE_SCALAR(asn);
|
||||||
|
UNSERIALIZE_SCALAR(asma);
|
||||||
|
UNSERIALIZE_SCALAR(fonr);
|
||||||
|
UNSERIALIZE_SCALAR(fonw);
|
||||||
|
UNSERIALIZE_SCALAR(valid);
|
||||||
|
}
|
||||||
|
}
|
101
src/arch/alpha/regfile.cc
Normal file
101
src/arch/alpha/regfile.cc
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003-2005 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Steve Reinhardt
|
||||||
|
* Gabe Black
|
||||||
|
* Kevin Lim
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "arch/alpha/regfile.hh"
|
||||||
|
#include "cpu/thread_context.hh"
|
||||||
|
|
||||||
|
namespace AlphaISA
|
||||||
|
{
|
||||||
|
void
|
||||||
|
RegFile::serialize(std::ostream &os)
|
||||||
|
{
|
||||||
|
intRegFile.serialize(os);
|
||||||
|
floatRegFile.serialize(os);
|
||||||
|
miscRegFile.serialize(os);
|
||||||
|
SERIALIZE_SCALAR(pc);
|
||||||
|
SERIALIZE_SCALAR(npc);
|
||||||
|
#if FULL_SYSTEM
|
||||||
|
SERIALIZE_SCALAR(intrflag);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RegFile::unserialize(Checkpoint *cp, const std::string §ion)
|
||||||
|
{
|
||||||
|
intRegFile.unserialize(cp, section);
|
||||||
|
floatRegFile.unserialize(cp, section);
|
||||||
|
miscRegFile.unserialize(cp, section);
|
||||||
|
UNSERIALIZE_SCALAR(pc);
|
||||||
|
UNSERIALIZE_SCALAR(npc);
|
||||||
|
#if FULL_SYSTEM
|
||||||
|
UNSERIALIZE_SCALAR(intrflag);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
copyRegs(ThreadContext *src, ThreadContext *dest)
|
||||||
|
{
|
||||||
|
// First loop through the integer registers.
|
||||||
|
for (int i = 0; i < NumIntRegs; ++i) {
|
||||||
|
dest->setIntReg(i, src->readIntReg(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then loop through the floating point registers.
|
||||||
|
for (int i = 0; i < TheISA::NumFloatRegs; ++i) {
|
||||||
|
dest->setFloatRegBits(i, src->readFloatRegBits(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy misc. registers
|
||||||
|
copyMiscRegs(src, dest);
|
||||||
|
|
||||||
|
// Lastly copy PC/NPC
|
||||||
|
dest->setPC(src->readPC());
|
||||||
|
dest->setNextPC(src->readNextPC());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
copyMiscRegs(ThreadContext *src, ThreadContext *dest)
|
||||||
|
{
|
||||||
|
dest->setMiscReg(AlphaISA::MISCREG_FPCR,
|
||||||
|
src->readMiscReg(AlphaISA::MISCREG_FPCR));
|
||||||
|
dest->setMiscReg(AlphaISA::MISCREG_UNIQ,
|
||||||
|
src->readMiscReg(AlphaISA::MISCREG_UNIQ));
|
||||||
|
dest->setMiscReg(AlphaISA::MISCREG_LOCKFLAG,
|
||||||
|
src->readMiscReg(AlphaISA::MISCREG_LOCKFLAG));
|
||||||
|
dest->setMiscReg(AlphaISA::MISCREG_LOCKADDR,
|
||||||
|
src->readMiscReg(AlphaISA::MISCREG_LOCKADDR));
|
||||||
|
|
||||||
|
#if FULL_SYSTEM
|
||||||
|
copyIprs(src, dest);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,8 +31,11 @@
|
||||||
#ifndef __ARCH_ALPHA_REGFILE_HH__
|
#ifndef __ARCH_ALPHA_REGFILE_HH__
|
||||||
#define __ARCH_ALPHA_REGFILE_HH__
|
#define __ARCH_ALPHA_REGFILE_HH__
|
||||||
|
|
||||||
#include "arch/alpha/types.hh"
|
|
||||||
#include "arch/alpha/isa_traits.hh"
|
#include "arch/alpha/isa_traits.hh"
|
||||||
|
#include "arch/alpha/floatregfile.hh"
|
||||||
|
#include "arch/alpha/intregfile.hh"
|
||||||
|
#include "arch/alpha/miscregfile.hh"
|
||||||
|
#include "arch/alpha/types.hh"
|
||||||
#include "sim/faults.hh"
|
#include "sim/faults.hh"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -45,111 +48,6 @@ class ThreadContext;
|
||||||
namespace AlphaISA
|
namespace AlphaISA
|
||||||
{
|
{
|
||||||
|
|
||||||
static inline std::string getIntRegName(RegIndex)
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline std::string getFloatRegName(RegIndex)
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline std::string getMiscRegName(RegIndex)
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
class IntRegFile
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
IntReg regs[NumIntRegs];
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
IntReg readReg(int intReg)
|
|
||||||
{
|
|
||||||
return regs[intReg];
|
|
||||||
}
|
|
||||||
|
|
||||||
Fault setReg(int intReg, const IntReg &val)
|
|
||||||
{
|
|
||||||
regs[intReg] = val;
|
|
||||||
return NoFault;
|
|
||||||
}
|
|
||||||
|
|
||||||
void serialize(std::ostream &os);
|
|
||||||
|
|
||||||
void unserialize(Checkpoint *cp, const std::string §ion);
|
|
||||||
|
|
||||||
void clear()
|
|
||||||
{ bzero(regs, sizeof(regs)); }
|
|
||||||
};
|
|
||||||
|
|
||||||
class FloatRegFile
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
union {
|
|
||||||
uint64_t q[NumFloatRegs]; // integer qword view
|
|
||||||
double d[NumFloatRegs]; // double-precision floating point view
|
|
||||||
};
|
|
||||||
|
|
||||||
void serialize(std::ostream &os);
|
|
||||||
|
|
||||||
void unserialize(Checkpoint *cp, const std::string §ion);
|
|
||||||
|
|
||||||
void clear()
|
|
||||||
{ bzero(d, sizeof(d)); }
|
|
||||||
};
|
|
||||||
|
|
||||||
class MiscRegFile {
|
|
||||||
protected:
|
|
||||||
uint64_t fpcr; // floating point condition codes
|
|
||||||
uint64_t uniq; // process-unique register
|
|
||||||
bool lock_flag; // lock flag for LL/SC
|
|
||||||
Addr lock_addr; // lock address for LL/SC
|
|
||||||
|
|
||||||
public:
|
|
||||||
MiscReg readReg(int misc_reg);
|
|
||||||
|
|
||||||
MiscReg readRegWithEffect(int misc_reg, Fault &fault,
|
|
||||||
ThreadContext *tc);
|
|
||||||
|
|
||||||
//These functions should be removed once the simplescalar cpu model
|
|
||||||
//has been replaced.
|
|
||||||
int getInstAsid();
|
|
||||||
int getDataAsid();
|
|
||||||
|
|
||||||
Fault setReg(int misc_reg, const MiscReg &val);
|
|
||||||
|
|
||||||
Fault setRegWithEffect(int misc_reg, const MiscReg &val,
|
|
||||||
ThreadContext *tc);
|
|
||||||
|
|
||||||
void clear()
|
|
||||||
{
|
|
||||||
fpcr = uniq = 0;
|
|
||||||
lock_flag = 0;
|
|
||||||
lock_addr = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void serialize(std::ostream &os);
|
|
||||||
|
|
||||||
void unserialize(Checkpoint *cp, const std::string §ion);
|
|
||||||
#if FULL_SYSTEM
|
|
||||||
protected:
|
|
||||||
typedef uint64_t InternalProcReg;
|
|
||||||
|
|
||||||
InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs
|
|
||||||
|
|
||||||
private:
|
|
||||||
InternalProcReg readIpr(int idx, Fault &fault, ThreadContext *tc);
|
|
||||||
|
|
||||||
Fault setIpr(int idx, InternalProcReg val, ThreadContext *tc);
|
|
||||||
#endif
|
|
||||||
friend class RegFile;
|
|
||||||
};
|
|
||||||
|
|
||||||
class RegFile {
|
class RegFile {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -215,22 +113,20 @@ namespace AlphaISA
|
||||||
return miscRegFile.readReg(miscReg);
|
return miscRegFile.readReg(miscReg);
|
||||||
}
|
}
|
||||||
|
|
||||||
MiscReg readMiscRegWithEffect(int miscReg,
|
MiscReg readMiscRegWithEffect(int miscReg, ThreadContext *tc)
|
||||||
Fault &fault, ThreadContext *tc)
|
|
||||||
{
|
{
|
||||||
fault = NoFault;
|
return miscRegFile.readRegWithEffect(miscReg, tc);
|
||||||
return miscRegFile.readRegWithEffect(miscReg, fault, tc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault setMiscReg(int miscReg, const MiscReg &val)
|
void setMiscReg(int miscReg, const MiscReg &val)
|
||||||
{
|
{
|
||||||
return miscRegFile.setReg(miscReg, val);
|
miscRegFile.setReg(miscReg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault setMiscRegWithEffect(int miscReg, const MiscReg &val,
|
void setMiscRegWithEffect(int miscReg, const MiscReg &val,
|
||||||
ThreadContext * tc)
|
ThreadContext * tc)
|
||||||
{
|
{
|
||||||
return miscRegFile.setRegWithEffect(miscReg, val, tc);
|
miscRegFile.setRegWithEffect(miscReg, val, tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatReg readFloatReg(int floatReg)
|
FloatReg readFloatReg(int floatReg)
|
||||||
|
@ -253,26 +149,24 @@ namespace AlphaISA
|
||||||
return readFloatRegBits(floatReg);
|
return readFloatRegBits(floatReg);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault setFloatReg(int floatReg, const FloatReg &val)
|
void setFloatReg(int floatReg, const FloatReg &val)
|
||||||
{
|
{
|
||||||
floatRegFile.d[floatReg] = val;
|
floatRegFile.d[floatReg] = val;
|
||||||
return NoFault;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault setFloatReg(int floatReg, const FloatReg &val, int width)
|
void setFloatReg(int floatReg, const FloatReg &val, int width)
|
||||||
{
|
{
|
||||||
return setFloatReg(floatReg, val);
|
setFloatReg(floatReg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault setFloatRegBits(int floatReg, const FloatRegBits &val)
|
void setFloatRegBits(int floatReg, const FloatRegBits &val)
|
||||||
{
|
{
|
||||||
floatRegFile.q[floatReg] = val;
|
floatRegFile.q[floatReg] = val;
|
||||||
return NoFault;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault setFloatRegBits(int floatReg, const FloatRegBits &val, int width)
|
void setFloatRegBits(int floatReg, const FloatRegBits &val, int width)
|
||||||
{
|
{
|
||||||
return setFloatRegBits(floatReg, val);
|
setFloatRegBits(floatReg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
IntReg readIntReg(int intReg)
|
IntReg readIntReg(int intReg)
|
||||||
|
@ -280,9 +174,9 @@ namespace AlphaISA
|
||||||
return intRegFile.readReg(intReg);
|
return intRegFile.readReg(intReg);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault setIntReg(int intReg, const IntReg &val)
|
void setIntReg(int intReg, const IntReg &val)
|
||||||
{
|
{
|
||||||
return intRegFile.setReg(intReg, val);
|
intRegFile.setReg(intReg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void serialize(std::ostream &os);
|
void serialize(std::ostream &os);
|
||||||
|
@ -298,10 +192,6 @@ namespace AlphaISA
|
||||||
void copyRegs(ThreadContext *src, ThreadContext *dest);
|
void copyRegs(ThreadContext *src, ThreadContext *dest);
|
||||||
|
|
||||||
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
|
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
|
||||||
void copyIprs(ThreadContext *src, ThreadContext *dest);
|
|
||||||
#endif
|
|
||||||
} // namespace AlphaISA
|
} // namespace AlphaISA
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
309
src/arch/alpha/remote_gdb.cc
Normal file
309
src/arch/alpha/remote_gdb.cc
Normal file
|
@ -0,0 +1,309 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2002-2005 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Nathan Binkert
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1990, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* This software was developed by the Computer Systems Engineering group
|
||||||
|
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||||
|
* contributed to Berkeley.
|
||||||
|
*
|
||||||
|
* All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Lawrence Berkeley Laboratories.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Jason R. Thorpe.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the NetBSD
|
||||||
|
* Foundation, Inc. and its contributors.
|
||||||
|
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $NetBSD: kgdb_stub.c,v 1.8 2001/07/07 22:58:00 wdk Exp $
|
||||||
|
*
|
||||||
|
* Taken from NetBSD
|
||||||
|
*
|
||||||
|
* "Stub" to allow remote cpu to debug over a serial line using gdb.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/signal.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "arch/alpha/kgdb.h"
|
||||||
|
#include "arch/alpha/remote_gdb.hh"
|
||||||
|
#include "arch/vtophys.hh"
|
||||||
|
#include "base/intmath.hh"
|
||||||
|
#include "base/remote_gdb.hh"
|
||||||
|
#include "base/socket.hh"
|
||||||
|
#include "base/trace.hh"
|
||||||
|
#include "config/full_system.hh"
|
||||||
|
#include "cpu/thread_context.hh"
|
||||||
|
#include "cpu/static_inst.hh"
|
||||||
|
#include "mem/physical.hh"
|
||||||
|
#include "mem/port.hh"
|
||||||
|
#include "sim/system.hh"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace TheISA;
|
||||||
|
|
||||||
|
RemoteGDB::RemoteGDB(System *_system, ThreadContext *c)
|
||||||
|
: BaseRemoteGDB(_system, c, KGDB_NUMREGS)
|
||||||
|
{
|
||||||
|
memset(gdbregs.regs, 0, gdbregs.bytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
// RemoteGDB::acc
|
||||||
|
//
|
||||||
|
// Determine if the mapping at va..(va+len) is valid.
|
||||||
|
//
|
||||||
|
bool
|
||||||
|
RemoteGDB::acc(Addr va, size_t len)
|
||||||
|
{
|
||||||
|
Addr last_va;
|
||||||
|
|
||||||
|
va = TheISA::TruncPage(va);
|
||||||
|
last_va = TheISA::RoundPage(va + len);
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (TheISA::IsK0Seg(va)) {
|
||||||
|
if (va < (TheISA::K0SegBase + pmem->size())) {
|
||||||
|
DPRINTF(GDBAcc, "acc: Mapping is valid K0SEG <= "
|
||||||
|
"%#x < K0SEG + size\n", va);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
DPRINTF(GDBAcc, "acc: Mapping invalid %#x > K0SEG + size\n",
|
||||||
|
va);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This code says that all accesses to palcode (instruction and data)
|
||||||
|
* are valid since there isn't a va->pa mapping because palcode is
|
||||||
|
* accessed physically. At some point this should probably be cleaned up
|
||||||
|
* but there is no easy way to do it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (AlphaISA::PcPAL(va) || va < 0x10000)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
Addr ptbr = context->readMiscReg(AlphaISA::IPR_PALtemp20);
|
||||||
|
TheISA::PageTableEntry pte = TheISA::kernel_pte_lookup(context->getPhysPort(), ptbr, va);
|
||||||
|
if (!pte.valid()) {
|
||||||
|
DPRINTF(GDBAcc, "acc: %#x pte is invalid\n", va);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
va += TheISA::PageBytes;
|
||||||
|
} while (va < last_va);
|
||||||
|
|
||||||
|
DPRINTF(GDBAcc, "acc: %#x mapping is valid\n", va);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
// RemoteGDB::getregs
|
||||||
|
//
|
||||||
|
// Translate the kernel debugger register format into
|
||||||
|
// the GDB register format.
|
||||||
|
void
|
||||||
|
RemoteGDB::getregs()
|
||||||
|
{
|
||||||
|
memset(gdbregs.regs, 0, gdbregs.bytes());
|
||||||
|
|
||||||
|
gdbregs.regs[KGDB_REG_PC] = context->readPC();
|
||||||
|
|
||||||
|
// @todo: Currently this is very Alpha specific.
|
||||||
|
if (AlphaISA::PcPAL(gdbregs.regs[KGDB_REG_PC])) {
|
||||||
|
for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
|
||||||
|
gdbregs.regs[i] = context->readIntReg(AlphaISA::reg_redir[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
|
||||||
|
gdbregs.regs[i] = context->readIntReg(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef KGDB_FP_REGS
|
||||||
|
for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) {
|
||||||
|
gdbregs.regs[i + KGDB_REG_F0] = context->readFloatRegBits(i);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
// RemoteGDB::setregs
|
||||||
|
//
|
||||||
|
// Translate the GDB register format into the kernel
|
||||||
|
// debugger register format.
|
||||||
|
//
|
||||||
|
void
|
||||||
|
RemoteGDB::setregs()
|
||||||
|
{
|
||||||
|
// @todo: Currently this is very Alpha specific.
|
||||||
|
if (AlphaISA::PcPAL(gdbregs.regs[KGDB_REG_PC])) {
|
||||||
|
for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
|
||||||
|
context->setIntReg(AlphaISA::reg_redir[i], gdbregs.regs[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
|
||||||
|
context->setIntReg(i, gdbregs.regs[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef KGDB_FP_REGS
|
||||||
|
for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) {
|
||||||
|
context->setFloatRegBits(i, gdbregs.regs[i + KGDB_REG_F0]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
context->setPC(gdbregs.regs[KGDB_REG_PC]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RemoteGDB::clearSingleStep()
|
||||||
|
{
|
||||||
|
DPRINTF(GDBMisc, "clearSingleStep bt_addr=%#x nt_addr=%#x\n",
|
||||||
|
takenBkpt, notTakenBkpt);
|
||||||
|
|
||||||
|
if (takenBkpt != 0)
|
||||||
|
clearTempBreakpoint(takenBkpt);
|
||||||
|
|
||||||
|
if (notTakenBkpt != 0)
|
||||||
|
clearTempBreakpoint(notTakenBkpt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RemoteGDB::setSingleStep()
|
||||||
|
{
|
||||||
|
Addr pc = context->readPC();
|
||||||
|
Addr npc, bpc;
|
||||||
|
bool set_bt = false;
|
||||||
|
|
||||||
|
npc = pc + sizeof(MachInst);
|
||||||
|
|
||||||
|
// User was stopped at pc, e.g. the instruction at pc was not
|
||||||
|
// executed.
|
||||||
|
MachInst inst = read<MachInst>(pc);
|
||||||
|
StaticInstPtr si(inst);
|
||||||
|
if (si->hasBranchTarget(pc, context, bpc)) {
|
||||||
|
// Don't bother setting a breakpoint on the taken branch if it
|
||||||
|
// is the same as the next pc
|
||||||
|
if (bpc != npc)
|
||||||
|
set_bt = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINTF(GDBMisc, "setSingleStep bt_addr=%#x nt_addr=%#x\n",
|
||||||
|
takenBkpt, notTakenBkpt);
|
||||||
|
|
||||||
|
setTempBreakpoint(notTakenBkpt = npc);
|
||||||
|
|
||||||
|
if (set_bt)
|
||||||
|
setTempBreakpoint(takenBkpt = bpc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write bytes to kernel address space for debugger.
|
||||||
|
bool
|
||||||
|
RemoteGDB::write(Addr vaddr, size_t size, const char *data)
|
||||||
|
{
|
||||||
|
if (BaseRemoteGDB::write(vaddr, size, data)) {
|
||||||
|
#ifdef IMB
|
||||||
|
alpha_pal_imb();
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
74
src/arch/alpha/remote_gdb.hh
Normal file
74
src/arch/alpha/remote_gdb.hh
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2002-2005 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Nathan Binkert
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ARCH_ALPHA_REMOTE_GDB_HH__
|
||||||
|
#define __ARCH_ALPHA_REMOTE_GDB_HH__
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "arch/alpha/types.hh"
|
||||||
|
#include "arch/alpha/kgdb.h"
|
||||||
|
#include "base/remote_gdb.hh"
|
||||||
|
#include "cpu/pc_event.hh"
|
||||||
|
#include "base/pollevent.hh"
|
||||||
|
#include "base/socket.hh"
|
||||||
|
|
||||||
|
class System;
|
||||||
|
class ThreadContext;
|
||||||
|
class PhysicalMemory;
|
||||||
|
|
||||||
|
namespace AlphaISA
|
||||||
|
{
|
||||||
|
class RemoteGDB : public BaseRemoteGDB
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
// Machine memory
|
||||||
|
bool write(Addr addr, size_t size, const char *data);
|
||||||
|
|
||||||
|
public:
|
||||||
|
RemoteGDB(System *system, ThreadContext *context);
|
||||||
|
|
||||||
|
bool acc(Addr addr, size_t len);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void getregs();
|
||||||
|
void setregs();
|
||||||
|
|
||||||
|
void clearSingleStep();
|
||||||
|
void setSingleStep();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
Addr notTakenBkpt;
|
||||||
|
Addr takenBkpt;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __ARCH_ALPHA_REMOTE_GDB_H__ */
|
|
@ -40,329 +40,331 @@
|
||||||
#include "sim/system.hh"
|
#include "sim/system.hh"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace AlphaISA;
|
|
||||||
|
|
||||||
ProcessInfo::ProcessInfo(ThreadContext *_tc)
|
namespace AlphaISA
|
||||||
: tc(_tc)
|
|
||||||
{
|
{
|
||||||
Addr addr = 0;
|
ProcessInfo::ProcessInfo(ThreadContext *_tc)
|
||||||
|
: tc(_tc)
|
||||||
|
{
|
||||||
|
Addr addr = 0;
|
||||||
|
|
||||||
VirtualPort *vp;
|
VirtualPort *vp;
|
||||||
|
|
||||||
vp = tc->getVirtPort();
|
vp = tc->getVirtPort();
|
||||||
|
|
||||||
if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr))
|
if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr))
|
||||||
panic("thread info not compiled into kernel\n");
|
panic("thread info not compiled into kernel\n");
|
||||||
thread_info_size = vp->readGtoH<int32_t>(addr);
|
thread_info_size = vp->readGtoH<int32_t>(addr);
|
||||||
|
|
||||||
if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr))
|
if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr))
|
||||||
panic("thread info not compiled into kernel\n");
|
panic("thread info not compiled into kernel\n");
|
||||||
task_struct_size = vp->readGtoH<int32_t>(addr);
|
task_struct_size = vp->readGtoH<int32_t>(addr);
|
||||||
|
|
||||||
if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr))
|
if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr))
|
||||||
panic("thread info not compiled into kernel\n");
|
panic("thread info not compiled into kernel\n");
|
||||||
task_off = vp->readGtoH<int32_t>(addr);
|
task_off = vp->readGtoH<int32_t>(addr);
|
||||||
|
|
||||||
if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr))
|
if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr))
|
||||||
panic("thread info not compiled into kernel\n");
|
panic("thread info not compiled into kernel\n");
|
||||||
pid_off = vp->readGtoH<int32_t>(addr);
|
pid_off = vp->readGtoH<int32_t>(addr);
|
||||||
|
|
||||||
if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr))
|
if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr))
|
||||||
panic("thread info not compiled into kernel\n");
|
panic("thread info not compiled into kernel\n");
|
||||||
name_off = vp->readGtoH<int32_t>(addr);
|
name_off = vp->readGtoH<int32_t>(addr);
|
||||||
|
|
||||||
tc->delVirtPort(vp);
|
tc->delVirtPort(vp);
|
||||||
}
|
|
||||||
|
|
||||||
Addr
|
|
||||||
ProcessInfo::task(Addr ksp) const
|
|
||||||
{
|
|
||||||
Addr base = ksp & ~0x3fff;
|
|
||||||
if (base == ULL(0xfffffc0000000000))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
Addr tsk;
|
|
||||||
|
|
||||||
VirtualPort *vp;
|
|
||||||
|
|
||||||
vp = tc->getVirtPort();
|
|
||||||
tsk = vp->readGtoH<Addr>(base + task_off);
|
|
||||||
tc->delVirtPort(vp);
|
|
||||||
|
|
||||||
return tsk;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ProcessInfo::pid(Addr ksp) const
|
|
||||||
{
|
|
||||||
Addr task = this->task(ksp);
|
|
||||||
if (!task)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
uint16_t pd;
|
|
||||||
|
|
||||||
VirtualPort *vp;
|
|
||||||
|
|
||||||
vp = tc->getVirtPort();
|
|
||||||
pd = vp->readGtoH<uint16_t>(task + pid_off);
|
|
||||||
tc->delVirtPort(vp);
|
|
||||||
|
|
||||||
return pd;
|
|
||||||
}
|
|
||||||
|
|
||||||
string
|
|
||||||
ProcessInfo::name(Addr ksp) const
|
|
||||||
{
|
|
||||||
Addr task = this->task(ksp);
|
|
||||||
if (!task)
|
|
||||||
return "console";
|
|
||||||
|
|
||||||
char comm[256];
|
|
||||||
CopyStringOut(tc, comm, task + name_off, sizeof(comm));
|
|
||||||
if (!comm[0])
|
|
||||||
return "startup";
|
|
||||||
|
|
||||||
return comm;
|
|
||||||
}
|
|
||||||
|
|
||||||
StackTrace::StackTrace()
|
|
||||||
: tc(0), stack(64)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
StackTrace::StackTrace(ThreadContext *_tc, StaticInstPtr inst)
|
|
||||||
: tc(0), stack(64)
|
|
||||||
{
|
|
||||||
trace(_tc, inst);
|
|
||||||
}
|
|
||||||
|
|
||||||
StackTrace::~StackTrace()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
StackTrace::trace(ThreadContext *_tc, bool is_call)
|
|
||||||
{
|
|
||||||
tc = _tc;
|
|
||||||
|
|
||||||
bool usermode = (tc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0;
|
|
||||||
|
|
||||||
Addr pc = tc->readNextPC();
|
|
||||||
bool kernel = tc->getSystemPtr()->kernelStart <= pc &&
|
|
||||||
pc <= tc->getSystemPtr()->kernelEnd;
|
|
||||||
|
|
||||||
if (usermode) {
|
|
||||||
stack.push_back(user);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!kernel) {
|
Addr
|
||||||
stack.push_back(console);
|
ProcessInfo::task(Addr ksp) const
|
||||||
return;
|
{
|
||||||
|
Addr base = ksp & ~0x3fff;
|
||||||
|
if (base == ULL(0xfffffc0000000000))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Addr tsk;
|
||||||
|
|
||||||
|
VirtualPort *vp;
|
||||||
|
|
||||||
|
vp = tc->getVirtPort();
|
||||||
|
tsk = vp->readGtoH<Addr>(base + task_off);
|
||||||
|
tc->delVirtPort(vp);
|
||||||
|
|
||||||
|
return tsk;
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
|
int
|
||||||
Addr ksp = tc->readIntReg(TheISA::StackPointerReg);
|
ProcessInfo::pid(Addr ksp) const
|
||||||
Addr bottom = ksp & ~0x3fff;
|
{
|
||||||
Addr addr;
|
Addr task = this->task(ksp);
|
||||||
|
if (!task)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (is_call) {
|
uint16_t pd;
|
||||||
if (!symtab->findNearestAddr(pc, addr))
|
|
||||||
panic("could not find address %#x", pc);
|
|
||||||
|
|
||||||
stack.push_back(addr);
|
VirtualPort *vp;
|
||||||
pc = tc->readPC();
|
|
||||||
|
vp = tc->getVirtPort();
|
||||||
|
pd = vp->readGtoH<uint16_t>(task + pid_off);
|
||||||
|
tc->delVirtPort(vp);
|
||||||
|
|
||||||
|
return pd;
|
||||||
}
|
}
|
||||||
|
|
||||||
Addr ra;
|
string
|
||||||
int size;
|
ProcessInfo::name(Addr ksp) const
|
||||||
|
{
|
||||||
|
Addr task = this->task(ksp);
|
||||||
|
if (!task)
|
||||||
|
return "console";
|
||||||
|
|
||||||
while (ksp > bottom) {
|
char comm[256];
|
||||||
if (!symtab->findNearestAddr(pc, addr))
|
CopyStringOut(tc, comm, task + name_off, sizeof(comm));
|
||||||
panic("could not find symbol for pc=%#x", pc);
|
if (!comm[0])
|
||||||
assert(pc >= addr && "symbol botch: callpc < func");
|
return "startup";
|
||||||
|
|
||||||
stack.push_back(addr);
|
return comm;
|
||||||
|
}
|
||||||
|
|
||||||
if (isEntry(addr))
|
StackTrace::StackTrace()
|
||||||
|
: tc(0), stack(64)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
StackTrace::StackTrace(ThreadContext *_tc, StaticInstPtr inst)
|
||||||
|
: tc(0), stack(64)
|
||||||
|
{
|
||||||
|
trace(_tc, inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
StackTrace::~StackTrace()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
StackTrace::trace(ThreadContext *_tc, bool is_call)
|
||||||
|
{
|
||||||
|
tc = _tc;
|
||||||
|
|
||||||
|
bool usermode = (tc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0;
|
||||||
|
|
||||||
|
Addr pc = tc->readNextPC();
|
||||||
|
bool kernel = tc->getSystemPtr()->kernelStart <= pc &&
|
||||||
|
pc <= tc->getSystemPtr()->kernelEnd;
|
||||||
|
|
||||||
|
if (usermode) {
|
||||||
|
stack.push_back(user);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (decodePrologue(ksp, pc, addr, size, ra)) {
|
if (!kernel) {
|
||||||
if (!ra)
|
stack.push_back(console);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
|
||||||
|
Addr ksp = tc->readIntReg(TheISA::StackPointerReg);
|
||||||
|
Addr bottom = ksp & ~0x3fff;
|
||||||
|
Addr addr;
|
||||||
|
|
||||||
|
if (is_call) {
|
||||||
|
if (!symtab->findNearestAddr(pc, addr))
|
||||||
|
panic("could not find address %#x", pc);
|
||||||
|
|
||||||
|
stack.push_back(addr);
|
||||||
|
pc = tc->readPC();
|
||||||
|
}
|
||||||
|
|
||||||
|
Addr ra;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
while (ksp > bottom) {
|
||||||
|
if (!symtab->findNearestAddr(pc, addr))
|
||||||
|
panic("could not find symbol for pc=%#x", pc);
|
||||||
|
assert(pc >= addr && "symbol botch: callpc < func");
|
||||||
|
|
||||||
|
stack.push_back(addr);
|
||||||
|
|
||||||
|
if (isEntry(addr))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (size <= 0) {
|
if (decodePrologue(ksp, pc, addr, size, ra)) {
|
||||||
|
if (!ra)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (size <= 0) {
|
||||||
|
stack.push_back(unknown);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pc = ra;
|
||||||
|
ksp += size;
|
||||||
|
} else {
|
||||||
stack.push_back(unknown);
|
stack.push_back(unknown);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pc = ra;
|
bool kernel = tc->getSystemPtr()->kernelStart <= pc &&
|
||||||
ksp += size;
|
pc <= tc->getSystemPtr()->kernelEnd;
|
||||||
} else {
|
if (!kernel)
|
||||||
stack.push_back(unknown);
|
return;
|
||||||
return;
|
|
||||||
|
if (stack.size() >= 1000)
|
||||||
|
panic("unwinding too far");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool kernel = tc->getSystemPtr()->kernelStart <= pc &&
|
panic("unwinding too far");
|
||||||
pc <= tc->getSystemPtr()->kernelEnd;
|
|
||||||
if (!kernel)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (stack.size() >= 1000)
|
|
||||||
panic("unwinding too far");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
panic("unwinding too far");
|
bool
|
||||||
}
|
StackTrace::isEntry(Addr addr)
|
||||||
|
{
|
||||||
|
if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp12))
|
||||||
|
return true;
|
||||||
|
|
||||||
bool
|
if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp7))
|
||||||
StackTrace::isEntry(Addr addr)
|
return true;
|
||||||
{
|
|
||||||
if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp12))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp7))
|
if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp11))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp11))
|
if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp21))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp21))
|
if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp9))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp9))
|
if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp2))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp2))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
StackTrace::decodeStack(MachInst inst, int &disp)
|
|
||||||
{
|
|
||||||
// lda $sp, -disp($sp)
|
|
||||||
//
|
|
||||||
// Opcode<31:26> == 0x08
|
|
||||||
// RA<25:21> == 30
|
|
||||||
// RB<20:16> == 30
|
|
||||||
// Disp<15:0>
|
|
||||||
const MachInst mem_mask = 0xffff0000;
|
|
||||||
const MachInst lda_pattern = 0x23de0000;
|
|
||||||
const MachInst lda_disp_mask = 0x0000ffff;
|
|
||||||
|
|
||||||
// subq $sp, disp, $sp
|
|
||||||
// addq $sp, disp, $sp
|
|
||||||
//
|
|
||||||
// Opcode<31:26> == 0x10
|
|
||||||
// RA<25:21> == 30
|
|
||||||
// Lit<20:13>
|
|
||||||
// One<12> = 1
|
|
||||||
// Func<11:5> == 0x20 (addq)
|
|
||||||
// Func<11:5> == 0x29 (subq)
|
|
||||||
// RC<4:0> == 30
|
|
||||||
const MachInst intop_mask = 0xffe01fff;
|
|
||||||
const MachInst addq_pattern = 0x43c0141e;
|
|
||||||
const MachInst subq_pattern = 0x43c0153e;
|
|
||||||
const MachInst intop_disp_mask = 0x001fe000;
|
|
||||||
const int intop_disp_shift = 13;
|
|
||||||
|
|
||||||
if ((inst & mem_mask) == lda_pattern)
|
|
||||||
disp = -sext<16>(inst & lda_disp_mask);
|
|
||||||
else if ((inst & intop_mask) == addq_pattern)
|
|
||||||
disp = -int((inst & intop_disp_mask) >> intop_disp_shift);
|
|
||||||
else if ((inst & intop_mask) == subq_pattern)
|
|
||||||
disp = int((inst & intop_disp_mask) >> intop_disp_shift);
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
StackTrace::decodeSave(MachInst inst, int ®, int &disp)
|
|
||||||
{
|
|
||||||
// lda $stq, disp($sp)
|
|
||||||
//
|
|
||||||
// Opcode<31:26> == 0x08
|
|
||||||
// RA<25:21> == ?
|
|
||||||
// RB<20:16> == 30
|
|
||||||
// Disp<15:0>
|
|
||||||
const MachInst stq_mask = 0xfc1f0000;
|
|
||||||
const MachInst stq_pattern = 0xb41e0000;
|
|
||||||
const MachInst stq_disp_mask = 0x0000ffff;
|
|
||||||
const MachInst reg_mask = 0x03e00000;
|
|
||||||
const int reg_shift = 21;
|
|
||||||
|
|
||||||
if ((inst & stq_mask) == stq_pattern) {
|
|
||||||
reg = (inst & reg_mask) >> reg_shift;
|
|
||||||
disp = sext<16>(inst & stq_disp_mask);
|
|
||||||
} else {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
bool
|
||||||
}
|
StackTrace::decodeStack(MachInst inst, int &disp)
|
||||||
|
{
|
||||||
|
// lda $sp, -disp($sp)
|
||||||
|
//
|
||||||
|
// Opcode<31:26> == 0x08
|
||||||
|
// RA<25:21> == 30
|
||||||
|
// RB<20:16> == 30
|
||||||
|
// Disp<15:0>
|
||||||
|
const MachInst mem_mask = 0xffff0000;
|
||||||
|
const MachInst lda_pattern = 0x23de0000;
|
||||||
|
const MachInst lda_disp_mask = 0x0000ffff;
|
||||||
|
|
||||||
/*
|
// subq $sp, disp, $sp
|
||||||
* Decode the function prologue for the function we're in, and note
|
// addq $sp, disp, $sp
|
||||||
* which registers are stored where, and how large the stack frame is.
|
//
|
||||||
*/
|
// Opcode<31:26> == 0x10
|
||||||
bool
|
// RA<25:21> == 30
|
||||||
StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
|
// Lit<20:13>
|
||||||
int &size, Addr &ra)
|
// One<12> = 1
|
||||||
{
|
// Func<11:5> == 0x20 (addq)
|
||||||
size = 0;
|
// Func<11:5> == 0x29 (subq)
|
||||||
ra = 0;
|
// RC<4:0> == 30
|
||||||
|
const MachInst intop_mask = 0xffe01fff;
|
||||||
|
const MachInst addq_pattern = 0x43c0141e;
|
||||||
|
const MachInst subq_pattern = 0x43c0153e;
|
||||||
|
const MachInst intop_disp_mask = 0x001fe000;
|
||||||
|
const int intop_disp_shift = 13;
|
||||||
|
|
||||||
for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) {
|
if ((inst & mem_mask) == lda_pattern)
|
||||||
MachInst inst;
|
disp = -sext<16>(inst & lda_disp_mask);
|
||||||
CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst));
|
else if ((inst & intop_mask) == addq_pattern)
|
||||||
|
disp = -int((inst & intop_disp_mask) >> intop_disp_shift);
|
||||||
|
else if ((inst & intop_mask) == subq_pattern)
|
||||||
|
disp = int((inst & intop_disp_mask) >> intop_disp_shift);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
int reg, disp;
|
return true;
|
||||||
if (decodeStack(inst, disp)) {
|
}
|
||||||
if (size) {
|
|
||||||
// panic("decoding frame size again");
|
bool
|
||||||
return true;
|
StackTrace::decodeSave(MachInst inst, int ®, int &disp)
|
||||||
}
|
{
|
||||||
size += disp;
|
// lda $stq, disp($sp)
|
||||||
} else if (decodeSave(inst, reg, disp)) {
|
//
|
||||||
if (!ra && reg == ReturnAddressReg) {
|
// Opcode<31:26> == 0x08
|
||||||
CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr));
|
// RA<25:21> == ?
|
||||||
if (!ra) {
|
// RB<20:16> == 30
|
||||||
// panic("no return address value pc=%#x\n", pc);
|
// Disp<15:0>
|
||||||
return false;
|
const MachInst stq_mask = 0xfc1f0000;
|
||||||
|
const MachInst stq_pattern = 0xb41e0000;
|
||||||
|
const MachInst stq_disp_mask = 0x0000ffff;
|
||||||
|
const MachInst reg_mask = 0x03e00000;
|
||||||
|
const int reg_shift = 21;
|
||||||
|
|
||||||
|
if ((inst & stq_mask) == stq_pattern) {
|
||||||
|
reg = (inst & reg_mask) >> reg_shift;
|
||||||
|
disp = sext<16>(inst & stq_disp_mask);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decode the function prologue for the function we're in, and note
|
||||||
|
* which registers are stored where, and how large the stack frame is.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
|
||||||
|
int &size, Addr &ra)
|
||||||
|
{
|
||||||
|
size = 0;
|
||||||
|
ra = 0;
|
||||||
|
|
||||||
|
for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) {
|
||||||
|
MachInst inst;
|
||||||
|
CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst));
|
||||||
|
|
||||||
|
int reg, disp;
|
||||||
|
if (decodeStack(inst, disp)) {
|
||||||
|
if (size) {
|
||||||
|
// panic("decoding frame size again");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
size += disp;
|
||||||
|
} else if (decodeSave(inst, reg, disp)) {
|
||||||
|
if (!ra && reg == ReturnAddressReg) {
|
||||||
|
CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr));
|
||||||
|
if (!ra) {
|
||||||
|
// panic("no return address value pc=%#x\n", pc);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TRACING_ON
|
#if TRACING_ON
|
||||||
void
|
void
|
||||||
StackTrace::dump()
|
StackTrace::dump()
|
||||||
{
|
{
|
||||||
StringWrap name(tc->getCpuPtr()->name());
|
StringWrap name(tc->getCpuPtr()->name());
|
||||||
SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
|
SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
|
||||||
|
|
||||||
DPRINTFN("------ Stack ------\n");
|
DPRINTFN("------ Stack ------\n");
|
||||||
|
|
||||||
string symbol;
|
string symbol;
|
||||||
for (int i = 0, size = stack.size(); i < size; ++i) {
|
for (int i = 0, size = stack.size(); i < size; ++i) {
|
||||||
Addr addr = stack[size - i - 1];
|
Addr addr = stack[size - i - 1];
|
||||||
if (addr == user)
|
if (addr == user)
|
||||||
symbol = "user";
|
symbol = "user";
|
||||||
else if (addr == console)
|
else if (addr == console)
|
||||||
symbol = "console";
|
symbol = "console";
|
||||||
else if (addr == unknown)
|
else if (addr == unknown)
|
||||||
symbol = "unknown";
|
symbol = "unknown";
|
||||||
else
|
else
|
||||||
symtab->findSymbol(addr, symbol);
|
symtab->findSymbol(addr, symbol);
|
||||||
|
|
||||||
DPRINTFN("%#x: %s\n", addr, symbol);
|
DPRINTFN("%#x: %s\n", addr, symbol);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -35,87 +35,91 @@
|
||||||
#include "cpu/static_inst.hh"
|
#include "cpu/static_inst.hh"
|
||||||
|
|
||||||
class ThreadContext;
|
class ThreadContext;
|
||||||
class StackTrace;
|
|
||||||
|
|
||||||
class ProcessInfo
|
namespace AlphaISA
|
||||||
{
|
{
|
||||||
private:
|
class StackTrace;
|
||||||
ThreadContext *tc;
|
|
||||||
|
|
||||||
int thread_info_size;
|
class ProcessInfo
|
||||||
int task_struct_size;
|
|
||||||
int task_off;
|
|
||||||
int pid_off;
|
|
||||||
int name_off;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ProcessInfo(ThreadContext *_tc);
|
|
||||||
|
|
||||||
Addr task(Addr ksp) const;
|
|
||||||
int pid(Addr ksp) const;
|
|
||||||
std::string name(Addr ksp) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
class StackTrace
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
typedef TheISA::MachInst MachInst;
|
|
||||||
private:
|
|
||||||
ThreadContext *tc;
|
|
||||||
std::vector<Addr> stack;
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool isEntry(Addr addr);
|
|
||||||
bool decodePrologue(Addr sp, Addr callpc, Addr func, int &size, Addr &ra);
|
|
||||||
bool decodeSave(MachInst inst, int ®, int &disp);
|
|
||||||
bool decodeStack(MachInst inst, int &disp);
|
|
||||||
|
|
||||||
void trace(ThreadContext *tc, bool is_call);
|
|
||||||
|
|
||||||
public:
|
|
||||||
StackTrace();
|
|
||||||
StackTrace(ThreadContext *tc, StaticInstPtr inst);
|
|
||||||
~StackTrace();
|
|
||||||
|
|
||||||
void clear()
|
|
||||||
{
|
{
|
||||||
tc = 0;
|
private:
|
||||||
stack.clear();
|
ThreadContext *tc;
|
||||||
}
|
|
||||||
|
|
||||||
bool valid() const { return tc != NULL; }
|
int thread_info_size;
|
||||||
bool trace(ThreadContext *tc, StaticInstPtr inst);
|
int task_struct_size;
|
||||||
|
int task_off;
|
||||||
|
int pid_off;
|
||||||
|
int name_off;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const std::vector<Addr> &getstack() const { return stack; }
|
ProcessInfo(ThreadContext *_tc);
|
||||||
|
|
||||||
static const int user = 1;
|
Addr task(Addr ksp) const;
|
||||||
static const int console = 2;
|
int pid(Addr ksp) const;
|
||||||
static const int unknown = 3;
|
std::string name(Addr ksp) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class StackTrace
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
typedef TheISA::MachInst MachInst;
|
||||||
|
private:
|
||||||
|
ThreadContext *tc;
|
||||||
|
std::vector<Addr> stack;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isEntry(Addr addr);
|
||||||
|
bool decodePrologue(Addr sp, Addr callpc, Addr func, int &size, Addr &ra);
|
||||||
|
bool decodeSave(MachInst inst, int ®, int &disp);
|
||||||
|
bool decodeStack(MachInst inst, int &disp);
|
||||||
|
|
||||||
|
void trace(ThreadContext *tc, bool is_call);
|
||||||
|
|
||||||
|
public:
|
||||||
|
StackTrace();
|
||||||
|
StackTrace(ThreadContext *tc, StaticInstPtr inst);
|
||||||
|
~StackTrace();
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
tc = 0;
|
||||||
|
stack.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool valid() const { return tc != NULL; }
|
||||||
|
bool trace(ThreadContext *tc, StaticInstPtr inst);
|
||||||
|
|
||||||
|
public:
|
||||||
|
const std::vector<Addr> &getstack() const { return stack; }
|
||||||
|
|
||||||
|
static const int user = 1;
|
||||||
|
static const int console = 2;
|
||||||
|
static const int unknown = 3;
|
||||||
|
|
||||||
#if TRACING_ON
|
#if TRACING_ON
|
||||||
private:
|
private:
|
||||||
void dump();
|
void dump();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void dprintf() { if (DTRACE(Stack)) dump(); }
|
void dprintf() { if (DTRACE(Stack)) dump(); }
|
||||||
#else
|
#else
|
||||||
public:
|
public:
|
||||||
void dprintf() {}
|
void dprintf() {}
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
StackTrace::trace(ThreadContext *tc, StaticInstPtr inst)
|
StackTrace::trace(ThreadContext *tc, StaticInstPtr inst)
|
||||||
{
|
{
|
||||||
if (!inst->isCall() && !inst->isReturn())
|
if (!inst->isCall() && !inst->isReturn())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (valid())
|
if (valid())
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
trace(tc, !inst->isReturn());
|
trace(tc, !inst->isReturn());
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __ARCH_ALPHA_STACKTRACE_HH__
|
#endif // __ARCH_ALPHA_STACKTRACE_HH__
|
||||||
|
|
|
@ -29,10 +29,12 @@
|
||||||
* Nathan Binkert
|
* Nathan Binkert
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/signal.h>
|
||||||
|
|
||||||
#include "arch/alpha/ev5.hh"
|
#include "arch/alpha/ev5.hh"
|
||||||
#include "arch/alpha/system.hh"
|
#include "arch/alpha/system.hh"
|
||||||
|
#include "arch/alpha/remote_gdb.hh"
|
||||||
#include "arch/vtophys.hh"
|
#include "arch/vtophys.hh"
|
||||||
#include "base/remote_gdb.hh"
|
|
||||||
#include "base/loader/object_file.hh"
|
#include "base/loader/object_file.hh"
|
||||||
#include "base/loader/symtab.hh"
|
#include "base/loader/symtab.hh"
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
|
@ -196,7 +198,7 @@ AlphaSystem::setAlphaAccess(Addr access)
|
||||||
bool
|
bool
|
||||||
AlphaSystem::breakpoint()
|
AlphaSystem::breakpoint()
|
||||||
{
|
{
|
||||||
return remoteGDB[0]->trap(ALPHA_KENTRY_INT);
|
return remoteGDB[0]->trap(SIGTRAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -36,6 +36,7 @@
|
||||||
|
|
||||||
#include "arch/alpha/ev5.hh"
|
#include "arch/alpha/ev5.hh"
|
||||||
#include "arch/alpha/isa_traits.hh"
|
#include "arch/alpha/isa_traits.hh"
|
||||||
|
#include "arch/alpha/pagetable.hh"
|
||||||
#include "arch/alpha/utility.hh"
|
#include "arch/alpha/utility.hh"
|
||||||
#include "arch/alpha/vtophys.hh"
|
#include "arch/alpha/vtophys.hh"
|
||||||
#include "base/statistics.hh"
|
#include "base/statistics.hh"
|
||||||
|
@ -45,82 +46,87 @@
|
||||||
|
|
||||||
class ThreadContext;
|
class ThreadContext;
|
||||||
|
|
||||||
class AlphaTLB : public SimObject
|
namespace AlphaISA
|
||||||
{
|
{
|
||||||
protected:
|
class PTE;
|
||||||
typedef std::multimap<Addr, int> PageTable;
|
|
||||||
PageTable lookupTable; // Quick lookup into page table
|
|
||||||
|
|
||||||
AlphaISA::PTE *table; // the Page Table
|
class TLB : public SimObject
|
||||||
int size; // TLB Size
|
{
|
||||||
int nlu; // not last used entry (for replacement)
|
protected:
|
||||||
|
typedef std::multimap<Addr, int> PageTable;
|
||||||
|
PageTable lookupTable; // Quick lookup into page table
|
||||||
|
|
||||||
void nextnlu() { if (++nlu >= size) nlu = 0; }
|
PTE *table; // the Page Table
|
||||||
AlphaISA::PTE *lookup(Addr vpn, uint8_t asn) const;
|
int size; // TLB Size
|
||||||
|
int nlu; // not last used entry (for replacement)
|
||||||
|
|
||||||
public:
|
void nextnlu() { if (++nlu >= size) nlu = 0; }
|
||||||
AlphaTLB(const std::string &name, int size);
|
PTE *lookup(Addr vpn, uint8_t asn) const;
|
||||||
virtual ~AlphaTLB();
|
|
||||||
|
|
||||||
int getsize() const { return size; }
|
public:
|
||||||
|
TLB(const std::string &name, int size);
|
||||||
|
virtual ~TLB();
|
||||||
|
|
||||||
AlphaISA::PTE &index(bool advance = true);
|
int getsize() const { return size; }
|
||||||
void insert(Addr vaddr, AlphaISA::PTE &pte);
|
|
||||||
|
|
||||||
void flushAll();
|
PTE &index(bool advance = true);
|
||||||
void flushProcesses();
|
void insert(Addr vaddr, PTE &pte);
|
||||||
void flushAddr(Addr addr, uint8_t asn);
|
|
||||||
|
|
||||||
// static helper functions... really EV5 VM traits
|
void flushAll();
|
||||||
static bool validVirtualAddress(Addr vaddr) {
|
void flushProcesses();
|
||||||
// unimplemented bits must be all 0 or all 1
|
void flushAddr(Addr addr, uint8_t asn);
|
||||||
Addr unimplBits = vaddr & EV5::VAddrUnImplMask;
|
|
||||||
return (unimplBits == 0) || (unimplBits == EV5::VAddrUnImplMask);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Fault checkCacheability(RequestPtr &req);
|
// static helper functions... really EV5 VM traits
|
||||||
|
static bool validVirtualAddress(Addr vaddr) {
|
||||||
|
// unimplemented bits must be all 0 or all 1
|
||||||
|
Addr unimplBits = vaddr & EV5::VAddrUnImplMask;
|
||||||
|
return (unimplBits == 0) || (unimplBits == EV5::VAddrUnImplMask);
|
||||||
|
}
|
||||||
|
|
||||||
// Checkpointing
|
static Fault checkCacheability(RequestPtr &req);
|
||||||
virtual void serialize(std::ostream &os);
|
|
||||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
|
||||||
};
|
|
||||||
|
|
||||||
class AlphaITB : public AlphaTLB
|
// Checkpointing
|
||||||
{
|
virtual void serialize(std::ostream &os);
|
||||||
protected:
|
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||||
mutable Stats::Scalar<> hits;
|
};
|
||||||
mutable Stats::Scalar<> misses;
|
|
||||||
mutable Stats::Scalar<> acv;
|
|
||||||
mutable Stats::Formula accesses;
|
|
||||||
|
|
||||||
public:
|
class ITB : public TLB
|
||||||
AlphaITB(const std::string &name, int size);
|
{
|
||||||
virtual void regStats();
|
protected:
|
||||||
|
mutable Stats::Scalar<> hits;
|
||||||
|
mutable Stats::Scalar<> misses;
|
||||||
|
mutable Stats::Scalar<> acv;
|
||||||
|
mutable Stats::Formula accesses;
|
||||||
|
|
||||||
Fault translate(RequestPtr &req, ThreadContext *tc) const;
|
public:
|
||||||
};
|
ITB(const std::string &name, int size);
|
||||||
|
virtual void regStats();
|
||||||
|
|
||||||
class AlphaDTB : public AlphaTLB
|
Fault translate(RequestPtr &req, ThreadContext *tc) const;
|
||||||
{
|
};
|
||||||
protected:
|
|
||||||
mutable Stats::Scalar<> read_hits;
|
|
||||||
mutable Stats::Scalar<> read_misses;
|
|
||||||
mutable Stats::Scalar<> read_acv;
|
|
||||||
mutable Stats::Scalar<> read_accesses;
|
|
||||||
mutable Stats::Scalar<> write_hits;
|
|
||||||
mutable Stats::Scalar<> write_misses;
|
|
||||||
mutable Stats::Scalar<> write_acv;
|
|
||||||
mutable Stats::Scalar<> write_accesses;
|
|
||||||
Stats::Formula hits;
|
|
||||||
Stats::Formula misses;
|
|
||||||
Stats::Formula acv;
|
|
||||||
Stats::Formula accesses;
|
|
||||||
|
|
||||||
public:
|
class DTB : public TLB
|
||||||
AlphaDTB(const std::string &name, int size);
|
{
|
||||||
virtual void regStats();
|
protected:
|
||||||
|
mutable Stats::Scalar<> read_hits;
|
||||||
|
mutable Stats::Scalar<> read_misses;
|
||||||
|
mutable Stats::Scalar<> read_acv;
|
||||||
|
mutable Stats::Scalar<> read_accesses;
|
||||||
|
mutable Stats::Scalar<> write_hits;
|
||||||
|
mutable Stats::Scalar<> write_misses;
|
||||||
|
mutable Stats::Scalar<> write_acv;
|
||||||
|
mutable Stats::Scalar<> write_accesses;
|
||||||
|
Stats::Formula hits;
|
||||||
|
Stats::Formula misses;
|
||||||
|
Stats::Formula acv;
|
||||||
|
Stats::Formula accesses;
|
||||||
|
|
||||||
Fault translate(RequestPtr &req, ThreadContext *tc, bool write) const;
|
public:
|
||||||
};
|
DTB(const std::string &name, int size);
|
||||||
|
virtual void regStats();
|
||||||
|
|
||||||
|
Fault translate(RequestPtr &req, ThreadContext *tc, bool write) const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif // __ALPHA_MEMORY_HH__
|
#endif // __ALPHA_MEMORY_HH__
|
||||||
|
|
|
@ -42,12 +42,18 @@
|
||||||
namespace AlphaISA
|
namespace AlphaISA
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
inUserMode(ThreadContext *tc)
|
||||||
|
{
|
||||||
|
return (tc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline ExtMachInst
|
static inline ExtMachInst
|
||||||
makeExtMI(MachInst inst, ThreadContext * xc) {
|
makeExtMI(MachInst inst, Addr pc) {
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
ExtMachInst ext_inst = inst;
|
ExtMachInst ext_inst = inst;
|
||||||
if (xc->readPC() && 0x1)
|
if (pc && 0x1)
|
||||||
return ext_inst|=(static_cast<ExtMachInst>(xc->readPC() & 0x1) << 32);
|
return ext_inst|=(static_cast<ExtMachInst>(pc & 0x1) << 32);
|
||||||
else
|
else
|
||||||
return ext_inst;
|
return ext_inst;
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -220,20 +220,20 @@ namespace MipsISA
|
||||||
return miscRegFile[misc_reg];
|
return miscRegFile[misc_reg];
|
||||||
}
|
}
|
||||||
|
|
||||||
MiscReg readRegWithEffect(int misc_reg, Fault &fault, ThreadContext *tc)
|
MiscReg readRegWithEffect(int misc_reg, ThreadContext *tc)
|
||||||
{
|
{
|
||||||
return miscRegFile[misc_reg];
|
return miscRegFile[misc_reg];
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault setReg(int misc_reg, const MiscReg &val)
|
void setReg(int misc_reg, const MiscReg &val)
|
||||||
{
|
{
|
||||||
miscRegFile[misc_reg] = val; return NoFault;
|
miscRegFile[misc_reg] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault setRegWithEffect(int misc_reg, const MiscReg &val,
|
void setRegWithEffect(int misc_reg, const MiscReg &val,
|
||||||
ThreadContext *tc)
|
ThreadContext *tc)
|
||||||
{
|
{
|
||||||
miscRegFile[misc_reg] = val; return NoFault;
|
miscRegFile[misc_reg] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend class RegFile;
|
friend class RegFile;
|
||||||
|
|
|
@ -62,22 +62,20 @@ namespace MipsISA
|
||||||
return miscRegFile.readReg(miscReg);
|
return miscRegFile.readReg(miscReg);
|
||||||
}
|
}
|
||||||
|
|
||||||
MiscReg readMiscRegWithEffect(int miscReg,
|
MiscReg readMiscRegWithEffect(int miscReg, ThreadContext *tc)
|
||||||
Fault &fault, ThreadContext *tc)
|
|
||||||
{
|
{
|
||||||
fault = NoFault;
|
return miscRegFile.readRegWithEffect(miscReg, tc);
|
||||||
return miscRegFile.readRegWithEffect(miscReg, fault, tc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault setMiscReg(int miscReg, const MiscReg &val)
|
void setMiscReg(int miscReg, const MiscReg &val)
|
||||||
{
|
{
|
||||||
return miscRegFile.setReg(miscReg, val);
|
miscRegFile.setReg(miscReg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault setMiscRegWithEffect(int miscReg, const MiscReg &val,
|
void setMiscRegWithEffect(int miscReg, const MiscReg &val,
|
||||||
ThreadContext * tc)
|
ThreadContext * tc)
|
||||||
{
|
{
|
||||||
return miscRegFile.setRegWithEffect(miscReg, val, tc);
|
miscRegFile.setRegWithEffect(miscReg, val, tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatRegVal readFloatReg(int floatReg)
|
FloatRegVal readFloatReg(int floatReg)
|
||||||
|
@ -100,24 +98,24 @@ namespace MipsISA
|
||||||
return floatRegFile.readRegBits(floatReg,width);
|
return floatRegFile.readRegBits(floatReg,width);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault setFloatReg(int floatReg, const FloatRegVal &val)
|
void setFloatReg(int floatReg, const FloatRegVal &val)
|
||||||
{
|
{
|
||||||
return floatRegFile.setReg(floatReg, val, SingleWidth);
|
floatRegFile.setReg(floatReg, val, SingleWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault setFloatReg(int floatReg, const FloatRegVal &val, int width)
|
void setFloatReg(int floatReg, const FloatRegVal &val, int width)
|
||||||
{
|
{
|
||||||
return floatRegFile.setReg(floatReg, val, width);
|
floatRegFile.setReg(floatReg, val, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault setFloatRegBits(int floatReg, const FloatRegBits &val)
|
void setFloatRegBits(int floatReg, const FloatRegBits &val)
|
||||||
{
|
{
|
||||||
return floatRegFile.setRegBits(floatReg, val, SingleWidth);
|
floatRegFile.setRegBits(floatReg, val, SingleWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault setFloatRegBits(int floatReg, const FloatRegBits &val, int width)
|
void setFloatRegBits(int floatReg, const FloatRegBits &val, int width)
|
||||||
{
|
{
|
||||||
return floatRegFile.setRegBits(floatReg, val, width);
|
floatRegFile.setRegBits(floatReg, val, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
IntReg readIntReg(int intReg)
|
IntReg readIntReg(int intReg)
|
||||||
|
@ -125,9 +123,9 @@ namespace MipsISA
|
||||||
return intRegFile.readReg(intReg);
|
return intRegFile.readReg(intReg);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault setIntReg(int intReg, const IntReg &val)
|
void setIntReg(int intReg, const IntReg &val)
|
||||||
{
|
{
|
||||||
return intRegFile.setReg(intReg, val);
|
intRegFile.setReg(intReg, val);
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,9 @@
|
||||||
class ThreadContext;
|
class ThreadContext;
|
||||||
class StackTrace;
|
class StackTrace;
|
||||||
|
|
||||||
|
namespace MipsISA
|
||||||
|
{
|
||||||
|
|
||||||
class ProcessInfo
|
class ProcessInfo
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -118,4 +121,6 @@ StackTrace::trace(ThreadContext *tc, StaticInstPtr inst)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif // __ARCH_MIPS_STACKTRACE_HH__
|
#endif // __ARCH_MIPS_STACKTRACE_HH__
|
||||||
|
|
|
@ -54,7 +54,11 @@ base_sources = Split('''
|
||||||
|
|
||||||
# Full-system sources
|
# Full-system sources
|
||||||
full_system_sources = Split('''
|
full_system_sources = Split('''
|
||||||
ua2005.cc
|
arguments.cc
|
||||||
|
remote_gdb.cc
|
||||||
|
stacktrace.cc
|
||||||
|
system.cc
|
||||||
|
tlb.cc
|
||||||
vtophys.cc
|
vtophys.cc
|
||||||
''')
|
''')
|
||||||
|
|
||||||
|
|
73
src/arch/sparc/arguments.cc
Normal file
73
src/arch/sparc/arguments.cc
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003-2005 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Nathan Binkert
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "arch/sparc/arguments.hh"
|
||||||
|
#include "arch/sparc/vtophys.hh"
|
||||||
|
#include "cpu/thread_context.hh"
|
||||||
|
#include "mem/vport.hh"
|
||||||
|
|
||||||
|
using namespace SparcISA;
|
||||||
|
|
||||||
|
Arguments::Data::~Data()
|
||||||
|
{
|
||||||
|
while (!data.empty()) {
|
||||||
|
delete [] data.front();
|
||||||
|
data.pop_front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
Arguments::Data::alloc(size_t size)
|
||||||
|
{
|
||||||
|
char *buf = new char[size];
|
||||||
|
data.push_back(buf);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
Arguments::getArg(bool fp)
|
||||||
|
{
|
||||||
|
//The caller uses %o0-%05 for the first 6 arguments even if their floating
|
||||||
|
//point. Double precision floating point values take two registers/args.
|
||||||
|
//Quads, structs, and unions are passed as pointers. All arguments beyond
|
||||||
|
//the sixth are passed on the stack past the 16 word window save area,
|
||||||
|
//space for the struct/union return pointer, and space reserved for the
|
||||||
|
//first 6 arguments which the caller may use but doesn't have to.
|
||||||
|
if (number < 6) {
|
||||||
|
return tc->readIntReg(8 + number);
|
||||||
|
} else {
|
||||||
|
Addr sp = tc->readIntReg(14);
|
||||||
|
VirtualPort *vp = tc->getVirtPort(tc);
|
||||||
|
uint64_t arg = vp->read<uint64_t>(sp + 92 + (number-6) * sizeof(uint64_t));
|
||||||
|
tc->delVirtPort(vp);
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
149
src/arch/sparc/arguments.hh
Normal file
149
src/arch/sparc/arguments.hh
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003-2005 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Nathan Binkert
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ARCH_SPARC_ARGUMENTS_HH__
|
||||||
|
#define __ARCH_SPARC_ARGUMENTS_HH__
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "arch/sparc/vtophys.hh"
|
||||||
|
#include "base/refcnt.hh"
|
||||||
|
#include "sim/host.hh"
|
||||||
|
|
||||||
|
class ThreadContext;
|
||||||
|
|
||||||
|
namespace SparcISA {
|
||||||
|
|
||||||
|
class Arguments
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
ThreadContext *tc;
|
||||||
|
int number;
|
||||||
|
uint64_t getArg(bool fp = false);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
class Data : public RefCounted
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Data(){}
|
||||||
|
~Data();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::list<char *> data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
char *alloc(size_t size);
|
||||||
|
};
|
||||||
|
|
||||||
|
RefCountingPtr<Data> data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Arguments(ThreadContext *ctx, int n = 0)
|
||||||
|
: tc(ctx), number(n), data(NULL)
|
||||||
|
{ assert(number >= 0); data = new Data;}
|
||||||
|
Arguments(const Arguments &args)
|
||||||
|
: tc(args.tc), number(args.number), data(args.data) {}
|
||||||
|
~Arguments() {}
|
||||||
|
|
||||||
|
ThreadContext *getThreadContext() const { return tc; }
|
||||||
|
|
||||||
|
const Arguments &operator=(const Arguments &args) {
|
||||||
|
tc = args.tc;
|
||||||
|
number = args.number;
|
||||||
|
data = args.data;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Arguments &operator++() {
|
||||||
|
++number;
|
||||||
|
assert(number >= 0);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Arguments operator++(int) {
|
||||||
|
Arguments args = *this;
|
||||||
|
++number;
|
||||||
|
assert(number >= 0);
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
Arguments &operator--() {
|
||||||
|
--number;
|
||||||
|
assert(number >= 0);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Arguments operator--(int) {
|
||||||
|
Arguments args = *this;
|
||||||
|
--number;
|
||||||
|
assert(number >= 0);
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Arguments &operator+=(int index) {
|
||||||
|
number += index;
|
||||||
|
assert(number >= 0);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Arguments &operator-=(int index) {
|
||||||
|
number -= index;
|
||||||
|
assert(number >= 0);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Arguments operator[](int index) {
|
||||||
|
return Arguments(tc, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
operator T() {
|
||||||
|
assert(sizeof(T) <= sizeof(uint64_t));
|
||||||
|
T data = static_cast<T>(getArg());
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
operator T *() {
|
||||||
|
T *buf = (T *)data->alloc(sizeof(T));
|
||||||
|
CopyData(tc, buf, getArg(), sizeof(T));
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator char *() {
|
||||||
|
char *buf = data->alloc(2048);
|
||||||
|
CopyStringOut(tc, buf, getArg(), 2048);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}; // namespace SparcISA
|
||||||
|
|
||||||
|
#endif // __ARCH_SPARC_ARGUMENTS_HH__
|
|
@ -219,4 +219,4 @@ namespace SparcISA
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __ARCH_SPARC_TLB_HH__
|
#endif // __ARCH_SPARC_ASI_HH__
|
||||||
|
|
|
@ -33,12 +33,14 @@
|
||||||
|
|
||||||
#include "arch/sparc/faults.hh"
|
#include "arch/sparc/faults.hh"
|
||||||
#include "arch/sparc/isa_traits.hh"
|
#include "arch/sparc/isa_traits.hh"
|
||||||
#include "arch/sparc/process.hh"
|
#include "arch/sparc/types.hh"
|
||||||
#include "base/bitfield.hh"
|
#include "base/bitfield.hh"
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
|
#include "config/full_system.hh"
|
||||||
#include "cpu/base.hh"
|
#include "cpu/base.hh"
|
||||||
#include "cpu/thread_context.hh"
|
#include "cpu/thread_context.hh"
|
||||||
#if !FULL_SYSTEM
|
#if !FULL_SYSTEM
|
||||||
|
#include "arch/sparc/process.hh"
|
||||||
#include "mem/page_table.hh"
|
#include "mem/page_table.hh"
|
||||||
#include "sim/process.hh"
|
#include "sim/process.hh"
|
||||||
#endif
|
#endif
|
||||||
|
@ -48,214 +50,352 @@ using namespace std;
|
||||||
namespace SparcISA
|
namespace SparcISA
|
||||||
{
|
{
|
||||||
|
|
||||||
FaultName InternalProcessorError::_name = "intprocerr";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType InternalProcessorError::_trapType = 0x029;
|
SparcFault<PowerOnReset>::vals =
|
||||||
FaultPriority InternalProcessorError::_priority = 4;
|
{"power_on_reset", 0x001, 0, {H, H, H}};
|
||||||
FaultStat InternalProcessorError::_count;
|
|
||||||
|
|
||||||
FaultName MemAddressNotAligned::_name = "unalign";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType MemAddressNotAligned::_trapType = 0x034;
|
SparcFault<WatchDogReset>::vals =
|
||||||
FaultPriority MemAddressNotAligned::_priority = 10;
|
{"watch_dog_reset", 0x002, 120, {H, H, H}};
|
||||||
FaultStat MemAddressNotAligned::_count;
|
|
||||||
|
|
||||||
FaultName PowerOnReset::_name = "pow_reset";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType PowerOnReset::_trapType = 0x001;
|
SparcFault<ExternallyInitiatedReset>::vals =
|
||||||
FaultPriority PowerOnReset::_priority = 0;
|
{"externally_initiated_reset", 0x003, 110, {H, H, H}};
|
||||||
FaultStat PowerOnReset::_count;
|
|
||||||
|
|
||||||
FaultName WatchDogReset::_name = "watch_dog_reset";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType WatchDogReset::_trapType = 0x002;
|
SparcFault<SoftwareInitiatedReset>::vals =
|
||||||
FaultPriority WatchDogReset::_priority = 1;
|
{"software_initiated_reset", 0x004, 130, {SH, SH, H}};
|
||||||
FaultStat WatchDogReset::_count;
|
|
||||||
|
|
||||||
FaultName ExternallyInitiatedReset::_name = "extern_reset";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType ExternallyInitiatedReset::_trapType = 0x003;
|
SparcFault<REDStateException>::vals =
|
||||||
FaultPriority ExternallyInitiatedReset::_priority = 1;
|
{"RED_state_exception", 0x005, 1, {H, H, H}};
|
||||||
FaultStat ExternallyInitiatedReset::_count;
|
|
||||||
|
|
||||||
FaultName SoftwareInitiatedReset::_name = "software_reset";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType SoftwareInitiatedReset::_trapType = 0x004;
|
SparcFault<StoreError>::vals =
|
||||||
FaultPriority SoftwareInitiatedReset::_priority = 1;
|
{"store_error", 0x007, 201, {H, H, H}};
|
||||||
FaultStat SoftwareInitiatedReset::_count;
|
|
||||||
|
|
||||||
FaultName REDStateException::_name = "red_counte";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType REDStateException::_trapType = 0x005;
|
SparcFault<InstructionAccessException>::vals =
|
||||||
FaultPriority REDStateException::_priority = 1;
|
{"instruction_access_exception", 0x008, 300, {H, H, H}};
|
||||||
FaultStat REDStateException::_count;
|
|
||||||
|
|
||||||
FaultName InstructionAccessException::_name = "inst_access";
|
//XXX This trap is apparently dropped from ua2005
|
||||||
TrapType InstructionAccessException::_trapType = 0x008;
|
/*template<> SparcFaultBase::FaultVals
|
||||||
FaultPriority InstructionAccessException::_priority = 5;
|
SparcFault<InstructionAccessMMUMiss>::vals =
|
||||||
FaultStat InstructionAccessException::_count;
|
{"inst_mmu", 0x009, 2, {H, H, H}};*/
|
||||||
|
|
||||||
FaultName InstructionAccessMMUMiss::_name = "inst_mmu";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType InstructionAccessMMUMiss::_trapType = 0x009;
|
SparcFault<InstructionAccessError>::vals =
|
||||||
FaultPriority InstructionAccessMMUMiss::_priority = 2;
|
{"instruction_access_error", 0x00A, 400, {H, H, H}};
|
||||||
FaultStat InstructionAccessMMUMiss::_count;
|
|
||||||
|
|
||||||
FaultName InstructionAccessError::_name = "inst_error";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType InstructionAccessError::_trapType = 0x00A;
|
SparcFault<IllegalInstruction>::vals =
|
||||||
FaultPriority InstructionAccessError::_priority = 3;
|
{"illegal_instruction", 0x010, 620, {H, H, H}};
|
||||||
FaultStat InstructionAccessError::_count;
|
|
||||||
|
|
||||||
FaultName IllegalInstruction::_name = "illegal_inst";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType IllegalInstruction::_trapType = 0x010;
|
SparcFault<PrivilegedOpcode>::vals =
|
||||||
FaultPriority IllegalInstruction::_priority = 7;
|
{"privileged_opcode", 0x011, 700, {P, SH, SH}};
|
||||||
FaultStat IllegalInstruction::_count;
|
|
||||||
|
|
||||||
FaultName PrivilegedOpcode::_name = "priv_opcode";
|
//XXX This trap is apparently dropped from ua2005
|
||||||
TrapType PrivilegedOpcode::_trapType = 0x011;
|
/*template<> SparcFaultBase::FaultVals
|
||||||
FaultPriority PrivilegedOpcode::_priority = 6;
|
SparcFault<UnimplementedLDD>::vals =
|
||||||
FaultStat PrivilegedOpcode::_count;
|
{"unimp_ldd", 0x012, 6, {H, H, H}};*/
|
||||||
|
|
||||||
FaultName UnimplementedLDD::_name = "unimp_ldd";
|
//XXX This trap is apparently dropped from ua2005
|
||||||
TrapType UnimplementedLDD::_trapType = 0x012;
|
/*template<> SparcFaultBase::FaultVals
|
||||||
FaultPriority UnimplementedLDD::_priority = 6;
|
SparcFault<UnimplementedSTD>::vals =
|
||||||
FaultStat UnimplementedLDD::_count;
|
{"unimp_std", 0x013, 6, {H, H, H}};*/
|
||||||
|
|
||||||
FaultName UnimplementedSTD::_name = "unimp_std";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType UnimplementedSTD::_trapType = 0x013;
|
SparcFault<FpDisabled>::vals =
|
||||||
FaultPriority UnimplementedSTD::_priority = 6;
|
{"fp_disabled", 0x020, 800, {P, P, H}};
|
||||||
FaultStat UnimplementedSTD::_count;
|
|
||||||
|
|
||||||
FaultName FpDisabled::_name = "fp_disabled";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType FpDisabled::_trapType = 0x020;
|
SparcFault<FpExceptionIEEE754>::vals =
|
||||||
FaultPriority FpDisabled::_priority = 8;
|
{"fp_exception_ieee_754", 0x021, 1110, {P, P, H}};
|
||||||
FaultStat FpDisabled::_count;
|
|
||||||
|
|
||||||
FaultName FpExceptionIEEE754::_name = "fp_754";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType FpExceptionIEEE754::_trapType = 0x021;
|
SparcFault<FpExceptionOther>::vals =
|
||||||
FaultPriority FpExceptionIEEE754::_priority = 11;
|
{"fp_exception_other", 0x022, 1110, {P, P, H}};
|
||||||
FaultStat FpExceptionIEEE754::_count;
|
|
||||||
|
|
||||||
FaultName FpExceptionOther::_name = "fp_other";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType FpExceptionOther::_trapType = 0x022;
|
SparcFault<TagOverflow>::vals =
|
||||||
FaultPriority FpExceptionOther::_priority = 11;
|
{"tag_overflow", 0x023, 1400, {P, P, H}};
|
||||||
FaultStat FpExceptionOther::_count;
|
|
||||||
|
|
||||||
FaultName TagOverflow::_name = "tag_overflow";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType TagOverflow::_trapType = 0x023;
|
SparcFault<CleanWindow>::vals =
|
||||||
FaultPriority TagOverflow::_priority = 14;
|
{"clean_window", 0x024, 1010, {P, P, H}};
|
||||||
FaultStat TagOverflow::_count;
|
|
||||||
|
|
||||||
FaultName DivisionByZero::_name = "div_by_zero";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType DivisionByZero::_trapType = 0x028;
|
SparcFault<DivisionByZero>::vals =
|
||||||
FaultPriority DivisionByZero::_priority = 15;
|
{"division_by_zero", 0x028, 1500, {P, P, H}};
|
||||||
FaultStat DivisionByZero::_count;
|
|
||||||
|
|
||||||
FaultName DataAccessException::_name = "data_access";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType DataAccessException::_trapType = 0x030;
|
SparcFault<InternalProcessorError>::vals =
|
||||||
FaultPriority DataAccessException::_priority = 12;
|
{"internal_processor_error", 0x029, 4, {H, H, H}};
|
||||||
FaultStat DataAccessException::_count;
|
|
||||||
|
|
||||||
FaultName DataAccessMMUMiss::_name = "data_mmu";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType DataAccessMMUMiss::_trapType = 0x031;
|
SparcFault<InstructionInvalidTSBEntry>::vals =
|
||||||
FaultPriority DataAccessMMUMiss::_priority = 12;
|
{"instruction_invalid_tsb_entry", 0x02A, 210, {H, H, SH}};
|
||||||
FaultStat DataAccessMMUMiss::_count;
|
|
||||||
|
|
||||||
FaultName DataAccessError::_name = "data_error";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType DataAccessError::_trapType = 0x032;
|
SparcFault<DataInvalidTSBEntry>::vals =
|
||||||
FaultPriority DataAccessError::_priority = 12;
|
{"data_invalid_tsb_entry", 0x02B, 1203, {H, H, H}};
|
||||||
FaultStat DataAccessError::_count;
|
|
||||||
|
|
||||||
FaultName DataAccessProtection::_name = "data_protection";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType DataAccessProtection::_trapType = 0x033;
|
SparcFault<DataAccessException>::vals =
|
||||||
FaultPriority DataAccessProtection::_priority = 12;
|
{"data_access_exception", 0x030, 1201, {H, H, H}};
|
||||||
FaultStat DataAccessProtection::_count;
|
|
||||||
|
|
||||||
FaultName LDDFMemAddressNotAligned::_name = "unalign_lddf";
|
//XXX This trap is apparently dropped from ua2005
|
||||||
TrapType LDDFMemAddressNotAligned::_trapType = 0x035;
|
/*template<> SparcFaultBase::FaultVals
|
||||||
FaultPriority LDDFMemAddressNotAligned::_priority = 10;
|
SparcFault<DataAccessMMUMiss>::vals =
|
||||||
FaultStat LDDFMemAddressNotAligned::_count;
|
{"data_mmu", 0x031, 12, {H, H, H}};*/
|
||||||
|
|
||||||
FaultName STDFMemAddressNotAligned::_name = "unalign_stdf";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType STDFMemAddressNotAligned::_trapType = 0x036;
|
SparcFault<DataAccessError>::vals =
|
||||||
FaultPriority STDFMemAddressNotAligned::_priority = 10;
|
{"data_access_error", 0x032, 1210, {H, H, H}};
|
||||||
FaultStat STDFMemAddressNotAligned::_count;
|
|
||||||
|
|
||||||
FaultName PrivilegedAction::_name = "priv_action";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType PrivilegedAction::_trapType = 0x037;
|
SparcFault<DataAccessProtection>::vals =
|
||||||
FaultPriority PrivilegedAction::_priority = 11;
|
{"data_access_protection", 0x033, 1207, {H, H, H}};
|
||||||
FaultStat PrivilegedAction::_count;
|
|
||||||
|
|
||||||
FaultName LDQFMemAddressNotAligned::_name = "unalign_ldqf";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType LDQFMemAddressNotAligned::_trapType = 0x038;
|
SparcFault<MemAddressNotAligned>::vals =
|
||||||
FaultPriority LDQFMemAddressNotAligned::_priority = 10;
|
{"mem_address_not_aligned", 0x034, 1020, {H, H, H}};
|
||||||
FaultStat LDQFMemAddressNotAligned::_count;
|
|
||||||
|
|
||||||
FaultName STQFMemAddressNotAligned::_name = "unalign_stqf";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType STQFMemAddressNotAligned::_trapType = 0x039;
|
SparcFault<LDDFMemAddressNotAligned>::vals =
|
||||||
FaultPriority STQFMemAddressNotAligned::_priority = 10;
|
{"LDDF_mem_address_not_aligned", 0x035, 1010, {H, H, H}};
|
||||||
FaultStat STQFMemAddressNotAligned::_count;
|
|
||||||
|
|
||||||
FaultName AsyncDataError::_name = "async_data";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType AsyncDataError::_trapType = 0x040;
|
SparcFault<STDFMemAddressNotAligned>::vals =
|
||||||
FaultPriority AsyncDataError::_priority = 2;
|
{"STDF_mem_address_not_aligned", 0x036, 1010, {H, H, H}};
|
||||||
FaultStat AsyncDataError::_count;
|
|
||||||
|
|
||||||
FaultName CleanWindow::_name = "clean_win";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType CleanWindow::_trapType = 0x024;
|
SparcFault<PrivilegedAction>::vals =
|
||||||
FaultPriority CleanWindow::_priority = 10;
|
{"privileged_action", 0x037, 1110, {H, H, SH}};
|
||||||
FaultStat CleanWindow::_count;
|
|
||||||
|
|
||||||
//The enumerated faults
|
template<> SparcFaultBase::FaultVals
|
||||||
|
SparcFault<LDQFMemAddressNotAligned>::vals =
|
||||||
|
{"LDQF_mem_address_not_aligned", 0x038, 1010, {H, H, H}};
|
||||||
|
|
||||||
FaultName InterruptLevelN::_name = "interrupt_n";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType InterruptLevelN::_baseTrapType = 0x041;
|
SparcFault<STQFMemAddressNotAligned>::vals =
|
||||||
FaultStat InterruptLevelN::_count;
|
{"STQF_mem_address_not_aligned", 0x039, 1010, {H, H, H}};
|
||||||
|
|
||||||
FaultName SpillNNormal::_name = "spill_n_normal";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType SpillNNormal::_baseTrapType = 0x080;
|
SparcFault<InstructionRealTranslationMiss>::vals =
|
||||||
FaultPriority SpillNNormal::_priority = 9;
|
{"instruction_real_translation_miss", 0x03E, 208, {H, H, SH}};
|
||||||
FaultStat SpillNNormal::_count;
|
|
||||||
|
|
||||||
FaultName SpillNOther::_name = "spill_n_other";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType SpillNOther::_baseTrapType = 0x0A0;
|
SparcFault<DataRealTranslationMiss>::vals =
|
||||||
FaultPriority SpillNOther::_priority = 9;
|
{"data_real_translation_miss", 0x03F, 1203, {H, H, H}};
|
||||||
FaultStat SpillNOther::_count;
|
|
||||||
|
|
||||||
FaultName FillNNormal::_name = "fill_n_normal";
|
//XXX This trap is apparently dropped from ua2005
|
||||||
TrapType FillNNormal::_baseTrapType = 0x0C0;
|
/*template<> SparcFaultBase::FaultVals
|
||||||
FaultPriority FillNNormal::_priority = 9;
|
SparcFault<AsyncDataError>::vals =
|
||||||
FaultStat FillNNormal::_count;
|
{"async_data", 0x040, 2, {H, H, H}};*/
|
||||||
|
|
||||||
FaultName FillNOther::_name = "fill_n_other";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType FillNOther::_baseTrapType = 0x0E0;
|
SparcFault<InterruptLevelN>::vals =
|
||||||
FaultPriority FillNOther::_priority = 9;
|
{"interrupt_level_n", 0x041, 0, {P, P, SH}};
|
||||||
FaultStat FillNOther::_count;
|
|
||||||
|
|
||||||
FaultName TrapInstruction::_name = "trap_inst_n";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType TrapInstruction::_baseTrapType = 0x100;
|
SparcFault<HstickMatch>::vals =
|
||||||
FaultPriority TrapInstruction::_priority = 16;
|
{"hstick_match", 0x05E, 1601, {H, H, H}};
|
||||||
FaultStat TrapInstruction::_count;
|
|
||||||
|
template<> SparcFaultBase::FaultVals
|
||||||
|
SparcFault<TrapLevelZero>::vals =
|
||||||
|
{"trap_level_zero", 0x05F, 202, {H, H, SH}};
|
||||||
|
|
||||||
|
template<> SparcFaultBase::FaultVals
|
||||||
|
SparcFault<PAWatchpoint>::vals =
|
||||||
|
{"PA_watchpoint", 0x061, 1209, {H, H, H}};
|
||||||
|
|
||||||
|
template<> SparcFaultBase::FaultVals
|
||||||
|
SparcFault<VAWatchpoint>::vals =
|
||||||
|
{"VA_watchpoint", 0x062, 1120, {P, P, SH}};
|
||||||
|
|
||||||
|
template<> SparcFaultBase::FaultVals
|
||||||
|
SparcFault<FastInstructionAccessMMUMiss>::vals =
|
||||||
|
{"fast_instruction_access_MMU_miss", 0x064, 208, {H, H, SH}};
|
||||||
|
|
||||||
|
template<> SparcFaultBase::FaultVals
|
||||||
|
SparcFault<FastDataAccessMMUMiss>::vals =
|
||||||
|
{"fast_data_access_MMU_miss", 0x068, 1203, {H, H, H}};
|
||||||
|
|
||||||
|
template<> SparcFaultBase::FaultVals
|
||||||
|
SparcFault<FastDataAccessProtection>::vals =
|
||||||
|
{"fast_data_access_protection", 0x06C, 1207, {H, H, H}};
|
||||||
|
|
||||||
|
template<> SparcFaultBase::FaultVals
|
||||||
|
SparcFault<InstructionBreakpoint>::vals =
|
||||||
|
{"instruction_break", 0x076, 610, {H, H, H}};
|
||||||
|
|
||||||
|
template<> SparcFaultBase::FaultVals
|
||||||
|
SparcFault<CpuMondo>::vals =
|
||||||
|
{"cpu_mondo", 0x07C, 1608, {P, P, SH}};
|
||||||
|
|
||||||
|
template<> SparcFaultBase::FaultVals
|
||||||
|
SparcFault<DevMondo>::vals =
|
||||||
|
{"dev_mondo", 0x07D, 1611, {P, P, SH}};
|
||||||
|
|
||||||
|
template<> SparcFaultBase::FaultVals
|
||||||
|
SparcFault<ResumeableError>::vals =
|
||||||
|
{"resume_error", 0x07E, 3330, {P, P, SH}};
|
||||||
|
|
||||||
|
template<> SparcFaultBase::FaultVals
|
||||||
|
SparcFault<SpillNNormal>::vals =
|
||||||
|
{"spill_n_normal", 0x080, 900, {P, P, H}};
|
||||||
|
|
||||||
|
template<> SparcFaultBase::FaultVals
|
||||||
|
SparcFault<SpillNOther>::vals =
|
||||||
|
{"spill_n_other", 0x0A0, 900, {P, P, H}};
|
||||||
|
|
||||||
|
template<> SparcFaultBase::FaultVals
|
||||||
|
SparcFault<FillNNormal>::vals =
|
||||||
|
{"fill_n_normal", 0x0C0, 900, {P, P, H}};
|
||||||
|
|
||||||
|
template<> SparcFaultBase::FaultVals
|
||||||
|
SparcFault<FillNOther>::vals =
|
||||||
|
{"fill_n_other", 0x0E0, 900, {P, P, H}};
|
||||||
|
|
||||||
|
template<> SparcFaultBase::FaultVals
|
||||||
|
SparcFault<TrapInstruction>::vals =
|
||||||
|
{"trap_instruction", 0x100, 1602, {P, P, H}};
|
||||||
|
|
||||||
#if !FULL_SYSTEM
|
#if !FULL_SYSTEM
|
||||||
FaultName PageTableFault::_name = "page_table_fault";
|
template<> SparcFaultBase::FaultVals
|
||||||
TrapType PageTableFault::_trapType = 0x0000;
|
SparcFault<PageTableFault>::vals =
|
||||||
FaultPriority PageTableFault::_priority = 0;
|
{"page_table_fault", 0x0000, 0, {SH, SH, SH}};
|
||||||
FaultStat PageTableFault::_count;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This sets everything up for a normal trap except for actually jumping to
|
* This causes the thread context to enter RED state. This causes the side
|
||||||
* the handler. It will need to be expanded to include the state machine in
|
* effects which go with entering RED state because of a trap.
|
||||||
* the manual. Right now it assumes that traps will always be to the
|
|
||||||
* privileged level.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void doNormalFault(ThreadContext *tc, TrapType tt)
|
void enterREDState(ThreadContext *tc)
|
||||||
{
|
{
|
||||||
uint64_t TL = tc->readMiscReg(MISCREG_TL);
|
//@todo Disable the mmu?
|
||||||
uint64_t TSTATE = tc->readMiscReg(MISCREG_TSTATE);
|
//@todo Disable watchpoints?
|
||||||
uint64_t PSTATE = tc->readMiscReg(MISCREG_PSTATE);
|
MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE);
|
||||||
uint64_t HPSTATE = tc->readMiscReg(MISCREG_HPSTATE);
|
//HPSTATE.red = 1
|
||||||
uint64_t CCR = tc->readMiscReg(MISCREG_CCR);
|
HPSTATE |= (1 << 5);
|
||||||
uint64_t ASI = tc->readMiscReg(MISCREG_ASI);
|
//HPSTATE.hpriv = 1
|
||||||
uint64_t CWP = tc->readMiscReg(MISCREG_CWP);
|
HPSTATE |= (1 << 2);
|
||||||
uint64_t CANSAVE = tc->readMiscReg(MISCREG_CANSAVE);
|
tc->setMiscReg(MISCREG_HPSTATE, HPSTATE);
|
||||||
uint64_t GL = tc->readMiscReg(MISCREG_GL);
|
}
|
||||||
uint64_t PC = tc->readPC();
|
|
||||||
uint64_t NPC = tc->readNextPC();
|
/**
|
||||||
|
* This sets everything up for a RED state trap except for actually jumping to
|
||||||
|
* the handler.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void doREDFault(ThreadContext *tc, TrapType tt)
|
||||||
|
{
|
||||||
|
MiscReg TL = tc->readMiscReg(MISCREG_TL);
|
||||||
|
MiscReg TSTATE = tc->readMiscReg(MISCREG_TSTATE);
|
||||||
|
MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE);
|
||||||
|
MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE);
|
||||||
|
MiscReg CCR = tc->readMiscReg(MISCREG_CCR);
|
||||||
|
MiscReg ASI = tc->readMiscReg(MISCREG_ASI);
|
||||||
|
MiscReg CWP = tc->readMiscReg(MISCREG_CWP);
|
||||||
|
MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE);
|
||||||
|
MiscReg GL = tc->readMiscReg(MISCREG_GL);
|
||||||
|
MiscReg PC = tc->readPC();
|
||||||
|
MiscReg NPC = tc->readNextPC();
|
||||||
|
|
||||||
|
TL++;
|
||||||
|
|
||||||
|
//set TSTATE.gl to gl
|
||||||
|
replaceBits(TSTATE, 42, 40, GL);
|
||||||
|
//set TSTATE.ccr to ccr
|
||||||
|
replaceBits(TSTATE, 39, 32, CCR);
|
||||||
|
//set TSTATE.asi to asi
|
||||||
|
replaceBits(TSTATE, 31, 24, ASI);
|
||||||
|
//set TSTATE.pstate to pstate
|
||||||
|
replaceBits(TSTATE, 20, 8, PSTATE);
|
||||||
|
//set TSTATE.cwp to cwp
|
||||||
|
replaceBits(TSTATE, 4, 0, CWP);
|
||||||
|
|
||||||
|
//Write back TSTATE
|
||||||
|
tc->setMiscReg(MISCREG_TSTATE, TSTATE);
|
||||||
|
|
||||||
|
//set TPC to PC
|
||||||
|
tc->setMiscReg(MISCREG_TPC, PC);
|
||||||
|
//set TNPC to NPC
|
||||||
|
tc->setMiscReg(MISCREG_TNPC, NPC);
|
||||||
|
|
||||||
|
//set HTSTATE.hpstate to hpstate
|
||||||
|
tc->setMiscReg(MISCREG_HTSTATE, HPSTATE);
|
||||||
|
|
||||||
|
//TT = trap type;
|
||||||
|
tc->setMiscReg(MISCREG_TT, tt);
|
||||||
|
|
||||||
|
//Update GL
|
||||||
|
tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL));
|
||||||
|
|
||||||
|
//set PSTATE.mm to 00
|
||||||
|
//set PSTATE.pef to 1
|
||||||
|
PSTATE |= (1 << 4);
|
||||||
|
//set PSTATE.am to 0
|
||||||
|
PSTATE &= ~(1 << 3);
|
||||||
|
//set PSTATE.priv to 0
|
||||||
|
PSTATE &= ~(1 << 2);
|
||||||
|
//set PSTATE.ie to 0
|
||||||
|
PSTATE &= ~(1 << 1);
|
||||||
|
//set PSTATE.cle to 0
|
||||||
|
PSTATE &= ~(1 << 9);
|
||||||
|
//PSTATE.tle is unchanged
|
||||||
|
//XXX Where is the tct bit?
|
||||||
|
//set PSTATE.tct to 0
|
||||||
|
tc->setMiscReg(MISCREG_PSTATE, PSTATE);
|
||||||
|
|
||||||
|
//set HPSTATE.red to 1
|
||||||
|
HPSTATE |= (1 << 5);
|
||||||
|
//set HPSTATE.hpriv to 1
|
||||||
|
HPSTATE |= (1 << 2);
|
||||||
|
//set HPSTATE.ibe to 0
|
||||||
|
HPSTATE &= ~(1 << 10);
|
||||||
|
//set HPSTATE.tlz to 0
|
||||||
|
HPSTATE &= ~(1 << 0);
|
||||||
|
tc->setMiscReg(MISCREG_HPSTATE, HPSTATE);
|
||||||
|
|
||||||
|
bool changedCWP = true;
|
||||||
|
if(tt == 0x24)
|
||||||
|
CWP++;
|
||||||
|
else if(0x80 <= tt && tt <= 0xbf)
|
||||||
|
CWP += (CANSAVE + 2);
|
||||||
|
else if(0xc0 <= tt && tt <= 0xff)
|
||||||
|
CWP--;
|
||||||
|
else
|
||||||
|
changedCWP = false;
|
||||||
|
|
||||||
|
if(changedCWP)
|
||||||
|
{
|
||||||
|
CWP = (CWP + NWindows) % NWindows;
|
||||||
|
tc->setMiscRegWithEffect(MISCREG_CWP, CWP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This sets everything up for a normal trap except for actually jumping to
|
||||||
|
* the handler.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
|
||||||
|
{
|
||||||
|
MiscReg TL = tc->readMiscReg(MISCREG_TL);
|
||||||
|
MiscReg TSTATE = tc->readMiscReg(MISCREG_TSTATE);
|
||||||
|
MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE);
|
||||||
|
MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE);
|
||||||
|
MiscReg CCR = tc->readMiscReg(MISCREG_CCR);
|
||||||
|
MiscReg ASI = tc->readMiscReg(MISCREG_ASI);
|
||||||
|
MiscReg CWP = tc->readMiscReg(MISCREG_CWP);
|
||||||
|
MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE);
|
||||||
|
MiscReg GL = tc->readMiscReg(MISCREG_GL);
|
||||||
|
MiscReg PC = tc->readPC();
|
||||||
|
MiscReg NPC = tc->readNextPC();
|
||||||
|
|
||||||
//Increment the trap level
|
//Increment the trap level
|
||||||
TL++;
|
TL++;
|
||||||
|
@ -289,10 +429,10 @@ void doNormalFault(ThreadContext *tc, TrapType tt)
|
||||||
tc->setMiscReg(MISCREG_TT, tt);
|
tc->setMiscReg(MISCREG_TT, tt);
|
||||||
|
|
||||||
//Update the global register level
|
//Update the global register level
|
||||||
if(1/*We're delivering the trap in priveleged mode*/)
|
if(!gotoHpriv)
|
||||||
tc->setMiscReg(MISCREG_GL, max<int>(GL+1, MaxGL));
|
tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxPGL));
|
||||||
else
|
else
|
||||||
tc->setMiscReg(MISCREG_GL, max<int>(GL+1, MaxPGL));
|
tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL));
|
||||||
|
|
||||||
//PSTATE.mm is unchanged
|
//PSTATE.mm is unchanged
|
||||||
//PSTATE.pef = whether or not an fpu is present
|
//PSTATE.pef = whether or not an fpu is present
|
||||||
|
@ -301,7 +441,7 @@ void doNormalFault(ThreadContext *tc, TrapType tt)
|
||||||
PSTATE |= (1 << 4);
|
PSTATE |= (1 << 4);
|
||||||
//PSTATE.am = 0
|
//PSTATE.am = 0
|
||||||
PSTATE &= ~(1 << 3);
|
PSTATE &= ~(1 << 3);
|
||||||
if(1/*We're delivering the trap in priveleged mode*/)
|
if(!gotoHpriv)
|
||||||
{
|
{
|
||||||
//PSTATE.priv = 1
|
//PSTATE.priv = 1
|
||||||
PSTATE |= (1 << 2);
|
PSTATE |= (1 << 2);
|
||||||
|
@ -322,7 +462,7 @@ void doNormalFault(ThreadContext *tc, TrapType tt)
|
||||||
//XXX Where exactly is this field?
|
//XXX Where exactly is this field?
|
||||||
tc->setMiscReg(MISCREG_PSTATE, PSTATE);
|
tc->setMiscReg(MISCREG_PSTATE, PSTATE);
|
||||||
|
|
||||||
if(0/*We're delivering the trap in hyperprivileged mode*/)
|
if(gotoHpriv)
|
||||||
{
|
{
|
||||||
//HPSTATE.red = 0
|
//HPSTATE.red = 0
|
||||||
HPSTATE &= ~(1 << 5);
|
HPSTATE &= ~(1 << 5);
|
||||||
|
@ -351,47 +491,135 @@ void doNormalFault(ThreadContext *tc, TrapType tt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void getREDVector(Addr & PC, Addr & NPC)
|
||||||
|
{
|
||||||
|
//XXX The following constant might belong in a header file.
|
||||||
|
const Addr RSTVAddr = 0xFFFFFFFFF0000000ULL;
|
||||||
|
PC = RSTVAddr | 0xA0;
|
||||||
|
NPC = PC + sizeof(MachInst);
|
||||||
|
}
|
||||||
|
|
||||||
|
void getHyperVector(ThreadContext * tc, Addr & PC, Addr & NPC, MiscReg TT)
|
||||||
|
{
|
||||||
|
Addr HTBA = tc->readMiscReg(MISCREG_HTBA);
|
||||||
|
PC = (HTBA & ~mask(14)) | ((TT << 5) & mask(14));
|
||||||
|
NPC = PC + sizeof(MachInst);
|
||||||
|
}
|
||||||
|
|
||||||
|
void getPrivVector(ThreadContext * tc, Addr & PC, Addr & NPC, MiscReg TT, MiscReg TL)
|
||||||
|
{
|
||||||
|
Addr TBA = tc->readMiscReg(MISCREG_TBA);
|
||||||
|
PC = (TBA & ~mask(15)) |
|
||||||
|
(TL > 1 ? (1 << 14) : 0) |
|
||||||
|
((TT << 5) & mask(14));
|
||||||
|
NPC = PC + sizeof(MachInst);
|
||||||
|
}
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
|
|
||||||
void SparcFault::invoke(ThreadContext * tc)
|
void SparcFaultBase::invoke(ThreadContext * tc)
|
||||||
{
|
{
|
||||||
FaultBase::invoke(tc);
|
FaultBase::invoke(tc);
|
||||||
countStat()++;
|
countStat()++;
|
||||||
|
|
||||||
//Use the SPARC trap state machine
|
//We can refer to this to see what the trap level -was-, but something
|
||||||
/*// exception restart address
|
//in the middle could change it in the regfile out from under us.
|
||||||
if (setRestartAddress() || !tc->inPalMode())
|
MiscReg TL = tc->readMiscReg(MISCREG_TL);
|
||||||
tc->setMiscReg(AlphaISA::IPR_EXC_ADDR, tc->regs.pc);
|
MiscReg TT = tc->readMiscReg(MISCREG_TT);
|
||||||
|
MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE);
|
||||||
|
MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE);
|
||||||
|
|
||||||
if (skipFaultingInstruction()) {
|
Addr PC, NPC;
|
||||||
// traps... skip faulting instruction.
|
|
||||||
tc->setMiscReg(AlphaISA::IPR_EXC_ADDR,
|
PrivilegeLevel current;
|
||||||
tc->readMiscReg(AlphaISA::IPR_EXC_ADDR) + 4);
|
if(!(PSTATE & (1 << 2)))
|
||||||
|
current = User;
|
||||||
|
else if(!(HPSTATE & (1 << 2)))
|
||||||
|
current = Privileged;
|
||||||
|
else
|
||||||
|
current = Hyperprivileged;
|
||||||
|
|
||||||
|
PrivilegeLevel level = getNextLevel(current);
|
||||||
|
|
||||||
|
if(HPSTATE & (1 << 5) || TL == MaxTL - 1)
|
||||||
|
{
|
||||||
|
getREDVector(PC, NPC);
|
||||||
|
enterREDState(tc);
|
||||||
|
doREDFault(tc, TT);
|
||||||
|
}
|
||||||
|
else if(TL == MaxTL)
|
||||||
|
{
|
||||||
|
//Do error_state somehow?
|
||||||
|
//Probably inject a WDR fault using the interrupt mechanism.
|
||||||
|
//What should the PC and NPC be set to?
|
||||||
|
}
|
||||||
|
else if(TL > MaxPTL && level == Privileged)
|
||||||
|
{
|
||||||
|
//guest_watchdog fault
|
||||||
|
doNormalFault(tc, trapType(), true);
|
||||||
|
getHyperVector(tc, PC, NPC, 2);
|
||||||
|
}
|
||||||
|
else if(level == Hyperprivileged)
|
||||||
|
{
|
||||||
|
doNormalFault(tc, trapType(), true);
|
||||||
|
getHyperVector(tc, PC, NPC, trapType());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
doNormalFault(tc, trapType(), false);
|
||||||
|
getPrivVector(tc, PC, NPC, trapType(), TL+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tc->inPalMode())
|
tc->setPC(PC);
|
||||||
AlphaISA::swap_palshadow(&(tc->regs), true);
|
tc->setNextPC(NPC);
|
||||||
|
tc->setNextNPC(NPC + sizeof(MachInst));
|
||||||
tc->regs.pc = tc->readMiscReg(AlphaISA::IPR_PAL_BASE) + vect();
|
|
||||||
tc->regs.npc = tc->regs.pc + sizeof(MachInst);*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
void PowerOnReset::invoke(ThreadContext * tc)
|
||||||
|
|
||||||
#if !FULL_SYSTEM
|
|
||||||
|
|
||||||
void TrapInstruction::invoke(ThreadContext * tc)
|
|
||||||
{
|
{
|
||||||
// Should be handled in ISA.
|
//First, enter RED state.
|
||||||
|
enterREDState(tc);
|
||||||
|
|
||||||
|
//For SPARC, when a system is first started, there is a power
|
||||||
|
//on reset Trap which sets the processor into the following state.
|
||||||
|
//Bits that aren't set aren't defined on startup.
|
||||||
|
/*
|
||||||
|
tl = MaxTL;
|
||||||
|
gl = MaxGL;
|
||||||
|
|
||||||
|
tickFields.counter = 0; //The TICK register is unreadable bya
|
||||||
|
tickFields.npt = 1; //The TICK register is unreadable by by !priv
|
||||||
|
|
||||||
|
softint = 0; // Clear all the soft interrupt bits
|
||||||
|
tick_cmprFields.int_dis = 1; // disable timer compare interrupts
|
||||||
|
tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
|
||||||
|
stickFields.npt = 1; //The TICK register is unreadable by by !priv
|
||||||
|
stick_cmprFields.int_dis = 1; // disable timer compare interrupts
|
||||||
|
stick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
|
||||||
|
|
||||||
|
tt[tl] = _trapType;
|
||||||
|
pstate = 0; // fields 0 but pef
|
||||||
|
pstateFields.pef = 1;
|
||||||
|
|
||||||
|
hpstate = 0;
|
||||||
|
hpstateFields.red = 1;
|
||||||
|
hpstateFields.hpriv = 1;
|
||||||
|
hpstateFields.tlz = 0; // this is a guess
|
||||||
|
hintp = 0; // no interrupts pending
|
||||||
|
hstick_cmprFields.int_dis = 1; // disable timer compare interrupts
|
||||||
|
hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else // !FULL_SYSTEM
|
||||||
|
|
||||||
void SpillNNormal::invoke(ThreadContext *tc)
|
void SpillNNormal::invoke(ThreadContext *tc)
|
||||||
{
|
{
|
||||||
doNormalFault(tc, trapType());
|
doNormalFault(tc, trapType(), false);
|
||||||
|
|
||||||
Process *p = tc->getProcessPtr();
|
Process *p = tc->getProcessPtr();
|
||||||
|
|
||||||
//This will only work in faults from a SparcLiveProcess
|
//XXX This will only work in faults from a SparcLiveProcess
|
||||||
SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p);
|
SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p);
|
||||||
assert(lp);
|
assert(lp);
|
||||||
|
|
||||||
|
@ -404,15 +632,15 @@ void SpillNNormal::invoke(ThreadContext *tc)
|
||||||
|
|
||||||
void FillNNormal::invoke(ThreadContext *tc)
|
void FillNNormal::invoke(ThreadContext *tc)
|
||||||
{
|
{
|
||||||
doNormalFault(tc, trapType());
|
doNormalFault(tc, trapType(), false);
|
||||||
|
|
||||||
Process * p = tc->getProcessPtr();
|
Process * p = tc->getProcessPtr();
|
||||||
|
|
||||||
//This will only work in faults from a SparcLiveProcess
|
//XXX This will only work in faults from a SparcLiveProcess
|
||||||
SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p);
|
SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p);
|
||||||
assert(lp);
|
assert(lp);
|
||||||
|
|
||||||
//The adjust the PC and NPC
|
//Then adjust the PC and NPC
|
||||||
Addr fillStart = lp->readFillStart();
|
Addr fillStart = lp->readFillStart();
|
||||||
tc->setPC(fillStart);
|
tc->setPC(fillStart);
|
||||||
tc->setNextPC(fillStart + sizeof(MachInst));
|
tc->setNextPC(fillStart + sizeof(MachInst));
|
||||||
|
|
|
@ -42,63 +42,222 @@ namespace SparcISA
|
||||||
typedef uint32_t TrapType;
|
typedef uint32_t TrapType;
|
||||||
typedef uint32_t FaultPriority;
|
typedef uint32_t FaultPriority;
|
||||||
|
|
||||||
class SparcFault : public FaultBase
|
class SparcFaultBase : public FaultBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum PrivilegeLevel
|
||||||
|
{
|
||||||
|
U, User = U,
|
||||||
|
P, Privileged = P,
|
||||||
|
H, Hyperprivileged = H,
|
||||||
|
NumLevels,
|
||||||
|
SH = -1,
|
||||||
|
ShouldntHappen = SH
|
||||||
|
};
|
||||||
|
struct FaultVals
|
||||||
|
{
|
||||||
|
const FaultName name;
|
||||||
|
const TrapType trapType;
|
||||||
|
const FaultPriority priority;
|
||||||
|
const PrivilegeLevel nextPrivilegeLevel[NumLevels];
|
||||||
|
FaultStat count;
|
||||||
|
};
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
void invoke(ThreadContext * tc);
|
void invoke(ThreadContext * tc);
|
||||||
#endif
|
#endif
|
||||||
|
virtual FaultName name() = 0;
|
||||||
virtual TrapType trapType() = 0;
|
virtual TrapType trapType() = 0;
|
||||||
virtual FaultPriority priority() = 0;
|
virtual FaultPriority priority() = 0;
|
||||||
virtual FaultStat & countStat() = 0;
|
virtual FaultStat & countStat() = 0;
|
||||||
|
virtual PrivilegeLevel getNextLevel(PrivilegeLevel current) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class InternalProcessorError : public SparcFault
|
template<typename T>
|
||||||
|
class SparcFault : public SparcFaultBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
static FaultVals vals;
|
||||||
|
public:
|
||||||
|
FaultName name() {return vals.name;}
|
||||||
|
TrapType trapType() {return vals.trapType;}
|
||||||
|
FaultPriority priority() {return vals.priority;}
|
||||||
|
FaultStat & countStat() {return vals.count;}
|
||||||
|
PrivilegeLevel getNextLevel(PrivilegeLevel current)
|
||||||
|
{
|
||||||
|
return vals.nextPrivilegeLevel[current];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class PowerOnReset : public SparcFault<PowerOnReset>
|
||||||
|
{
|
||||||
|
void invoke(ThreadContext * tc);
|
||||||
|
};
|
||||||
|
|
||||||
|
class WatchDogReset : public SparcFault<WatchDogReset> {};
|
||||||
|
|
||||||
|
class ExternallyInitiatedReset : public SparcFault<ExternallyInitiatedReset> {};
|
||||||
|
|
||||||
|
class SoftwareInitiatedReset : public SparcFault<SoftwareInitiatedReset> {};
|
||||||
|
|
||||||
|
class REDStateException : public SparcFault<REDStateException> {};
|
||||||
|
|
||||||
|
class StoreError : public SparcFault<StoreError> {};
|
||||||
|
|
||||||
|
class InstructionAccessException : public SparcFault<InstructionAccessException> {};
|
||||||
|
|
||||||
|
//class InstructionAccessMMUMiss : public SparcFault<InstructionAccessMMUMiss> {};
|
||||||
|
|
||||||
|
class InstructionAccessError : public SparcFault<InstructionAccessError> {};
|
||||||
|
|
||||||
|
class IllegalInstruction : public SparcFault<IllegalInstruction> {};
|
||||||
|
|
||||||
|
class PrivilegedOpcode : public SparcFault<PrivilegedOpcode> {};
|
||||||
|
|
||||||
|
//class UnimplementedLDD : public SparcFault<UnimplementedLDD> {};
|
||||||
|
|
||||||
|
//class UnimplementedSTD : public SparcFault<UnimplementedSTD> {};
|
||||||
|
|
||||||
|
class FpDisabled : public SparcFault<FpDisabled> {};
|
||||||
|
|
||||||
|
class FpExceptionIEEE754 : public SparcFault<FpExceptionIEEE754> {};
|
||||||
|
|
||||||
|
class FpExceptionOther : public SparcFault<FpExceptionOther> {};
|
||||||
|
|
||||||
|
class TagOverflow : public SparcFault<TagOverflow> {};
|
||||||
|
|
||||||
|
class CleanWindow : public SparcFault<CleanWindow> {};
|
||||||
|
|
||||||
|
class DivisionByZero : public SparcFault<DivisionByZero> {};
|
||||||
|
|
||||||
|
class InternalProcessorError :
|
||||||
|
public SparcFault<InternalProcessorError>
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
public:
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
bool isMachineCheckFault() {return true;}
|
bool isMachineCheckFault() {return true;}
|
||||||
};
|
};
|
||||||
|
|
||||||
class MemAddressNotAligned : public SparcFault
|
class InstructionInvalidTSBEntry : public SparcFault<InstructionInvalidTSBEntry> {};
|
||||||
|
|
||||||
|
class DataInvalidTSBEntry : public SparcFault<DataInvalidTSBEntry> {};
|
||||||
|
|
||||||
|
class DataAccessException : public SparcFault<DataAccessException> {};
|
||||||
|
|
||||||
|
//class DataAccessMMUMiss : public SparcFault<DataAccessMMUMiss> {};
|
||||||
|
|
||||||
|
class DataAccessError : public SparcFault<DataAccessError> {};
|
||||||
|
|
||||||
|
class DataAccessProtection : public SparcFault<DataAccessProtection> {};
|
||||||
|
|
||||||
|
class MemAddressNotAligned :
|
||||||
|
public SparcFault<MemAddressNotAligned>
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
public:
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
bool isAlignmentFault() {return true;}
|
bool isAlignmentFault() {return true;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class LDDFMemAddressNotAligned : public SparcFault<LDDFMemAddressNotAligned> {};
|
||||||
|
|
||||||
|
class STDFMemAddressNotAligned : public SparcFault<STDFMemAddressNotAligned> {};
|
||||||
|
|
||||||
|
class PrivilegedAction : public SparcFault<PrivilegedAction> {};
|
||||||
|
|
||||||
|
class LDQFMemAddressNotAligned : public SparcFault<LDQFMemAddressNotAligned> {};
|
||||||
|
|
||||||
|
class STQFMemAddressNotAligned : public SparcFault<STQFMemAddressNotAligned> {};
|
||||||
|
|
||||||
|
class InstructionRealTranslationMiss :
|
||||||
|
public SparcFault<InstructionRealTranslationMiss> {};
|
||||||
|
|
||||||
|
class DataRealTranslationMiss : public SparcFault<DataRealTranslationMiss> {};
|
||||||
|
|
||||||
|
//class AsyncDataError : public SparcFault<AsyncDataError> {};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class EnumeratedFault : public SparcFault<T>
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
uint32_t _n;
|
||||||
|
public:
|
||||||
|
EnumeratedFault(uint32_t n) : SparcFault<T>(), _n(n) {}
|
||||||
|
TrapType trapType() {return SparcFault<T>::trapType() + _n;}
|
||||||
|
};
|
||||||
|
|
||||||
|
class InterruptLevelN : public EnumeratedFault<InterruptLevelN>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InterruptLevelN(uint32_t n) : EnumeratedFault<InterruptLevelN>(n) {;}
|
||||||
|
FaultPriority priority() {return 3200 - _n*100;}
|
||||||
|
};
|
||||||
|
|
||||||
|
class HstickMatch : public SparcFault<HstickMatch> {};
|
||||||
|
|
||||||
|
class TrapLevelZero : public SparcFault<TrapLevelZero> {};
|
||||||
|
|
||||||
|
class PAWatchpoint : public SparcFault<PAWatchpoint> {};
|
||||||
|
|
||||||
|
class VAWatchpoint : public SparcFault<VAWatchpoint> {};
|
||||||
|
|
||||||
|
class FastInstructionAccessMMUMiss :
|
||||||
|
public SparcFault<FastInstructionAccessMMUMiss> {};
|
||||||
|
|
||||||
|
class FastDataAccessMMUMiss : public SparcFault<FastDataAccessMMUMiss> {};
|
||||||
|
|
||||||
|
class FastDataAccessProtection : public SparcFault<FastDataAccessProtection> {};
|
||||||
|
|
||||||
|
class InstructionBreakpoint : public SparcFault<InstructionBreakpoint> {};
|
||||||
|
|
||||||
|
class CpuMondo : public SparcFault<CpuMondo> {};
|
||||||
|
|
||||||
|
class DevMondo : public SparcFault<DevMondo> {};
|
||||||
|
|
||||||
|
class ResumeableError : public SparcFault<ResumeableError> {};
|
||||||
|
|
||||||
|
class SpillNNormal : public EnumeratedFault<SpillNNormal>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SpillNNormal(uint32_t n) : EnumeratedFault<SpillNNormal>(n) {;}
|
||||||
|
//These need to be handled specially to enable spill traps in SE
|
||||||
#if !FULL_SYSTEM
|
#if !FULL_SYSTEM
|
||||||
class PageTableFault : public SparcFault
|
void invoke(ThreadContext * tc);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
class SpillNOther : public EnumeratedFault<SpillNOther>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SpillNOther(uint32_t n) : EnumeratedFault<SpillNOther>(n) {;}
|
||||||
|
};
|
||||||
|
|
||||||
|
class FillNNormal : public EnumeratedFault<FillNNormal>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FillNNormal(uint32_t n) : EnumeratedFault<FillNNormal>(n) {;}
|
||||||
|
//These need to be handled specially to enable fill traps in SE
|
||||||
|
#if !FULL_SYSTEM
|
||||||
|
void invoke(ThreadContext * tc);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
class FillNOther : public EnumeratedFault<FillNOther>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FillNOther(uint32_t n) : EnumeratedFault<FillNOther>(n) {;}
|
||||||
|
};
|
||||||
|
|
||||||
|
class TrapInstruction : public EnumeratedFault<TrapInstruction>
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
TrapInstruction(uint32_t n) : EnumeratedFault<TrapInstruction>(n) {;}
|
||||||
|
};
|
||||||
|
|
||||||
|
#if !FULL_SYSTEM
|
||||||
|
class PageTableFault : public SparcFault<PageTableFault>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
Addr vaddr;
|
Addr vaddr;
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
public:
|
||||||
PageTableFault(Addr va)
|
PageTableFault(Addr va) : vaddr(va) {}
|
||||||
: vaddr(va) {}
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
void invoke(ThreadContext * tc);
|
void invoke(ThreadContext * tc);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -118,504 +277,6 @@ static inline Fault genAlignmentFault()
|
||||||
return new MemAddressNotAligned;
|
return new MemAddressNotAligned;
|
||||||
}
|
}
|
||||||
|
|
||||||
class PowerOnReset : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class WatchDogReset : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class ExternallyInitiatedReset : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class SoftwareInitiatedReset : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class REDStateException : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class InstructionAccessException : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class InstructionAccessMMUMiss : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class InstructionAccessError : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class IllegalInstruction : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class PrivilegedOpcode : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class UnimplementedLDD : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class UnimplementedSTD : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class FpDisabled : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class FpExceptionIEEE754 : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class FpExceptionOther : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class TagOverflow : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class DivisionByZero : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class DataAccessException : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class DataAccessMMUMiss : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class DataAccessError : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class DataAccessProtection : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class LDDFMemAddressNotAligned : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class STDFMemAddressNotAligned : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class PrivilegedAction : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class LDQFMemAddressNotAligned : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class STQFMemAddressNotAligned : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class AsyncDataError : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class CleanWindow : public SparcFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _trapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
public:
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
TrapType trapType() {return _trapType;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class EnumeratedFault : public SparcFault
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
uint32_t _n;
|
|
||||||
virtual TrapType baseTrapType() = 0;
|
|
||||||
public:
|
|
||||||
EnumeratedFault(uint32_t n) : SparcFault() {_n = n;}
|
|
||||||
TrapType trapType() {return baseTrapType() + _n;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class InterruptLevelN : public EnumeratedFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _baseTrapType;
|
|
||||||
static FaultStat _count;
|
|
||||||
TrapType baseTrapType() {return _baseTrapType;}
|
|
||||||
public:
|
|
||||||
InterruptLevelN(uint32_t n) : EnumeratedFault(n) {;}
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
FaultPriority priority() {return 32 - _n;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class SpillNNormal : public EnumeratedFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _baseTrapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
TrapType baseTrapType() {return _baseTrapType;}
|
|
||||||
public:
|
|
||||||
SpillNNormal(uint32_t n) : EnumeratedFault(n) {;}
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
void invoke(ThreadContext * tc);
|
|
||||||
};
|
|
||||||
|
|
||||||
class SpillNOther : public EnumeratedFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _baseTrapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
TrapType baseTrapType() {return _baseTrapType;}
|
|
||||||
public:
|
|
||||||
SpillNOther(uint32_t n) : EnumeratedFault(n) {;}
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class FillNNormal : public EnumeratedFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _baseTrapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
TrapType baseTrapType() {return _baseTrapType;}
|
|
||||||
public:
|
|
||||||
FillNNormal(uint32_t n) : EnumeratedFault(n) {;}
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
void invoke(ThreadContext * tc);
|
|
||||||
};
|
|
||||||
|
|
||||||
class FillNOther : public EnumeratedFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _baseTrapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
TrapType baseTrapType() {return _baseTrapType;}
|
|
||||||
public:
|
|
||||||
FillNOther(uint32_t n) : EnumeratedFault(n) {;}
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class TrapInstruction : public EnumeratedFault
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static FaultName _name;
|
|
||||||
static TrapType _baseTrapType;
|
|
||||||
static FaultPriority _priority;
|
|
||||||
static FaultStat _count;
|
|
||||||
uint64_t syscall_num;
|
|
||||||
TrapType baseTrapType() {return _baseTrapType;}
|
|
||||||
public:
|
|
||||||
TrapInstruction(uint32_t n, uint64_t syscall) :
|
|
||||||
EnumeratedFault(n), syscall_num(syscall) {;}
|
|
||||||
FaultName name() {return _name;}
|
|
||||||
FaultPriority priority() {return _priority;}
|
|
||||||
FaultStat & countStat() {return _count;}
|
|
||||||
#if !FULL_SYSTEM
|
|
||||||
void invoke(ThreadContext * tc);
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // SparcISA namespace
|
} // SparcISA namespace
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,8 @@
|
||||||
#include "sim/byteswap.hh"
|
#include "sim/byteswap.hh"
|
||||||
#include "sim/serialize.hh"
|
#include "sim/serialize.hh"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
using namespace SparcISA;
|
using namespace SparcISA;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -55,7 +57,7 @@ string SparcISA::getFloatRegName(RegIndex index)
|
||||||
|
|
||||||
void FloatRegFile::clear()
|
void FloatRegFile::clear()
|
||||||
{
|
{
|
||||||
bzero(regSpace, sizeof(regSpace));
|
memset(regSpace, 0, sizeof(regSpace));
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatReg FloatRegFile::readReg(int floatReg, int width)
|
FloatReg FloatRegFile::readReg(int floatReg, int width)
|
||||||
|
|
92
src/arch/sparc/interrupts.hh
Normal file
92
src/arch/sparc/interrupts.hh
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Gabe Black
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ARCH_SPARC_INTERRUPT_HH__
|
||||||
|
#define __ARCH_SPARC_INTERRUPT_HH__
|
||||||
|
|
||||||
|
#include "arch/sparc/faults.hh"
|
||||||
|
|
||||||
|
namespace SparcISA
|
||||||
|
{
|
||||||
|
class Interrupts
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
Fault interrupts[NumInterruptLevels];
|
||||||
|
bool requested[NumInterruptLevels];
|
||||||
|
|
||||||
|
public:
|
||||||
|
Interrupts()
|
||||||
|
{
|
||||||
|
for(int x = 0; x < NumInterruptLevels; x++)
|
||||||
|
{
|
||||||
|
interrupts[x] = new InterruptLevelN(x);
|
||||||
|
requested[x] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void post(int int_num, int index)
|
||||||
|
{
|
||||||
|
if(int_num < 0 || int_num >= NumInterruptLevels)
|
||||||
|
panic("int_num out of bounds\n");
|
||||||
|
|
||||||
|
requested[int_num] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear(int int_num, int index)
|
||||||
|
{
|
||||||
|
requested[int_num] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_all()
|
||||||
|
{
|
||||||
|
for(int x = 0; x < NumInterruptLevels; x++)
|
||||||
|
requested[x] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check_interrupts(ThreadContext * tc) const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Fault getInterrupt(ThreadContext * tc)
|
||||||
|
{
|
||||||
|
return NoFault;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serialize(std::ostream &os)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void unserialize(Checkpoint *cp, const std::string §ion)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __ARCH_SPARC_INTERRUPT_HH__
|
|
@ -33,6 +33,8 @@
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
#include "sim/serialize.hh"
|
#include "sim/serialize.hh"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
using namespace SparcISA;
|
using namespace SparcISA;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -62,7 +64,7 @@ void IntRegFile::clear()
|
||||||
for (x = 0; x < MaxGL; x++)
|
for (x = 0; x < MaxGL; x++)
|
||||||
memset(regGlobals[x], 0, sizeof(IntReg) * RegsPerFrame);
|
memset(regGlobals[x], 0, sizeof(IntReg) * RegsPerFrame);
|
||||||
for(int x = 0; x < 2 * NWindows; x++)
|
for(int x = 0; x < 2 * NWindows; x++)
|
||||||
bzero(regSegments[x], sizeof(IntReg) * RegsPerFrame);
|
memset(regSegments[x], 0, sizeof(IntReg) * RegsPerFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
IntRegFile::IntRegFile()
|
IntRegFile::IntRegFile()
|
||||||
|
|
|
@ -346,22 +346,93 @@ decode OP default Unknown::unknown()
|
||||||
0x0: sra({{Rd = Rs1.sw >> (I ? SHCNT32 : Rs2<4:0>);}});
|
0x0: sra({{Rd = Rs1.sw >> (I ? SHCNT32 : Rs2<4:0>);}});
|
||||||
0x1: srax({{Rd = Rs1.sdw >> (I ? SHCNT64 : Rs2<5:0>);}});
|
0x1: srax({{Rd = Rs1.sdw >> (I ? SHCNT64 : Rs2<5:0>);}});
|
||||||
}
|
}
|
||||||
// XXX might want a format rdipr thing here
|
|
||||||
0x28: decode RS1 {
|
0x28: decode RS1 {
|
||||||
0xF: decode I {
|
0x00: NoPriv::rdy({{Rd = Y;}});
|
||||||
|
//1 should cause an illegal instruction exception
|
||||||
|
0x02: NoPriv::rdccr({{Rd = Ccr;}});
|
||||||
|
0x03: NoPriv::rdasi({{Rd = Asi;}});
|
||||||
|
0x04: PrivCheck::rdtick({{Rd = Tick;}}, {{Tick<63:>}});
|
||||||
|
0x05: NoPriv::rdpc({{
|
||||||
|
if(Pstate<3:>)
|
||||||
|
Rd = (xc->readPC())<31:0>;
|
||||||
|
else
|
||||||
|
Rd = xc->readPC();}});
|
||||||
|
0x06: NoPriv::rdfprs({{
|
||||||
|
//Wait for all fpops to finish.
|
||||||
|
Rd = Fprs;
|
||||||
|
}});
|
||||||
|
//7-14 should cause an illegal instruction exception
|
||||||
|
0x0F: decode I {
|
||||||
0x0: Nop::stbar({{/*stuff*/}});
|
0x0: Nop::stbar({{/*stuff*/}});
|
||||||
0x1: Nop::membar({{/*stuff*/}});
|
0x1: Nop::membar({{/*stuff*/}});
|
||||||
}
|
}
|
||||||
default: rdasr({{
|
0x10: Priv::rdpcr({{Rd = Pcr;}});
|
||||||
Rd = xc->readMiscRegWithEffect(RS1 + AsrStart, fault);
|
0x11: PrivCheck::rdpic({{Rd = Pic;}}, {{Pcr<0:>}});
|
||||||
|
//0x12 should cause an illegal instruction exception
|
||||||
|
0x13: NoPriv::rdgsr({{
|
||||||
|
if(Fprs<2:> == 0 || Pstate<4:> == 0)
|
||||||
|
Rd = Gsr;
|
||||||
|
else
|
||||||
|
fault = new FpDisabled;
|
||||||
}});
|
}});
|
||||||
|
//0x14-0x15 should cause an illegal instruction exception
|
||||||
|
0x16: Priv::rdsoftint({{Rd = Softint;}});
|
||||||
|
0x17: Priv::rdtick_cmpr({{Rd = TickCmpr;}});
|
||||||
|
0x18: PrivCheck::rdstick({{Rd = Stick}}, {{Stick<63:>}});
|
||||||
|
0x19: Priv::rdstick_cmpr({{Rd = StickCmpr;}});
|
||||||
|
//0x1A-0x1F should cause an illegal instruction exception
|
||||||
|
}
|
||||||
|
0x29: decode RS1 {
|
||||||
|
0x00: HPriv::rdhprhpstate({{Rd = Hpstate;}});
|
||||||
|
0x01: HPriv::rdhprhtstate({{
|
||||||
|
if(Tl == 0)
|
||||||
|
return new IllegalInstruction;
|
||||||
|
Rd = Htstate;
|
||||||
|
}});
|
||||||
|
//0x02 should cause an illegal instruction exception
|
||||||
|
0x03: HPriv::rdhprhintp({{Rd = Hintp;}});
|
||||||
|
//0x04 should cause an illegal instruction exception
|
||||||
|
0x05: HPriv::rdhprhtba({{Rd = Htba;}});
|
||||||
|
0x06: HPriv::rdhprhver({{Rd = Hver;}});
|
||||||
|
//0x07-0x1E should cause an illegal instruction exception
|
||||||
|
0x1F: HPriv::rdhprhstick_cmpr({{Rd = HstickCmpr;}});
|
||||||
|
}
|
||||||
|
0x2A: decode RS1 {
|
||||||
|
0x00: Priv::rdprtpc({{
|
||||||
|
if(Tl == 0)
|
||||||
|
return new IllegalInstruction;
|
||||||
|
Rd = Tpc;
|
||||||
|
}});
|
||||||
|
0x01: Priv::rdprtnpc({{
|
||||||
|
if(Tl == 0)
|
||||||
|
return new IllegalInstruction;
|
||||||
|
Rd = Tnpc;
|
||||||
|
}});
|
||||||
|
0x02: Priv::rdprtstate({{
|
||||||
|
if(Tl == 0)
|
||||||
|
return new IllegalInstruction;
|
||||||
|
Rd = Tstate;
|
||||||
|
}});
|
||||||
|
0x03: Priv::rdprtt({{
|
||||||
|
if(Tl == 0)
|
||||||
|
return new IllegalInstruction;
|
||||||
|
Rd = Tt;
|
||||||
|
}});
|
||||||
|
0x04: Priv::rdprtick({{Rd = Tick;}});
|
||||||
|
0x05: Priv::rdprtba({{Rd = Tba;}});
|
||||||
|
0x06: Priv::rdprpstate({{Rd = Pstate;}});
|
||||||
|
0x07: Priv::rdprtl({{Rd = Tl;}});
|
||||||
|
0x08: Priv::rdprpil({{Rd = Pil;}});
|
||||||
|
0x09: Priv::rdprcwp({{Rd = Cwp;}});
|
||||||
|
0x0A: Priv::rdprcansave({{Rd = Cansave;}});
|
||||||
|
0x0B: Priv::rdprcanrestore({{Rd = Canrestore;}});
|
||||||
|
0x0C: Priv::rdprcleanwin({{Rd = Cleanwin;}});
|
||||||
|
0x0D: Priv::rdprotherwin({{Rd = Otherwin;}});
|
||||||
|
0x0E: Priv::rdprwstate({{Rd = Wstate;}});
|
||||||
|
//0x0F should cause an illegal instruction exception
|
||||||
|
0x10: Priv::rdprgl({{Rd = Gl;}});
|
||||||
|
//0x11-0x1F should cause an illegal instruction exception
|
||||||
}
|
}
|
||||||
0x29: HPriv::rdhpr({{
|
|
||||||
Rd = xc->readMiscRegWithEffect(RS1 + HprStart, fault);
|
|
||||||
}});
|
|
||||||
0x2A: Priv::rdpr({{
|
|
||||||
Rd = xc->readMiscRegWithEffect(RS1 + PrStart, fault);
|
|
||||||
}});
|
|
||||||
0x2B: BasicOperate::flushw({{
|
0x2B: BasicOperate::flushw({{
|
||||||
if(NWindows - 2 - Cansave == 0)
|
if(NWindows - 2 - Cansave == 0)
|
||||||
{
|
{
|
||||||
|
@ -417,9 +488,35 @@ decode OP default Unknown::unknown()
|
||||||
0x6: movrg({{Rd = (Rs1.sdw > 0) ? Rs2_or_imm10 : Rd;}});
|
0x6: movrg({{Rd = (Rs1.sdw > 0) ? Rs2_or_imm10 : Rd;}});
|
||||||
0x7: movrge({{Rd = (Rs1.sdw >= 0) ? Rs2_or_imm10 : Rd;}});
|
0x7: movrge({{Rd = (Rs1.sdw >= 0) ? Rs2_or_imm10 : Rd;}});
|
||||||
}
|
}
|
||||||
0x30: wrasr({{
|
0x30: decode RD {
|
||||||
xc->setMiscRegWithEffect(RD + AsrStart, Rs1 ^ Rs2_or_imm13);
|
0x00: NoPriv::wry({{Y = Rs1 ^ Rs2_or_imm13;}});
|
||||||
}});
|
//0x01 should cause an illegal instruction exception
|
||||||
|
0x02: NoPriv::wrccr({{Ccr = Rs1 ^ Rs2_or_imm13;}});
|
||||||
|
0x03: NoPriv::wrasi({{Ccr = Rs1 ^ Rs2_or_imm13;}});
|
||||||
|
//0x04-0x05 should cause an illegal instruction exception
|
||||||
|
0x06: NoPriv::wrfprs({{Fprs = Rs1 ^ Rs2_or_imm13;}});
|
||||||
|
//0x07-0x0E should cause an illegal instruction exception
|
||||||
|
0x0F: Trap::softreset({{fault = new SoftwareInitiatedReset;}});
|
||||||
|
0x10: Priv::wrpcr({{Pcr = Rs1 ^ Rs2_or_imm13;}});
|
||||||
|
0x11: PrivCheck::wrpic({{Pic = Rs1 ^ Rs2_or_imm13;}}, {{Pcr<0:>}});
|
||||||
|
//0x12 should cause an illegal instruction exception
|
||||||
|
0x13: NoPriv::wrgsr({{
|
||||||
|
if(Fprs<2:> == 0 || Pstate<4:> == 0)
|
||||||
|
return new FpDisabled;
|
||||||
|
Gsr = Rs1 ^ Rs2_or_imm13;
|
||||||
|
}});
|
||||||
|
0x14: Priv::wrsoftint_set({{SoftintSet = Rs1 ^ Rs2_or_imm13;}});
|
||||||
|
0x15: Priv::wrsoftint_clr({{SoftintClr = Rs1 ^ Rs2_or_imm13;}});
|
||||||
|
0x16: Priv::wrsoftint({{Softint = Rs1 ^ Rs2_or_imm13;}});
|
||||||
|
0x17: Priv::wrtick_cmpr({{TickCmpr = Rs1 ^ Rs2_or_imm13;}});
|
||||||
|
0x18: NoPriv::wrstick({{
|
||||||
|
if(!Hpstate<2:>)
|
||||||
|
return new IllegalInstruction;
|
||||||
|
Stick = Rs1 ^ Rs2_or_imm13;
|
||||||
|
}});
|
||||||
|
0x19: Priv::wrstick_cmpr({{StickCmpr = Rs1 ^ Rs2_or_imm13;}});
|
||||||
|
//0x1A-0x1F should cause an illegal instruction exception
|
||||||
|
}
|
||||||
0x31: decode FCN {
|
0x31: decode FCN {
|
||||||
0x0: Priv::saved({{
|
0x0: Priv::saved({{
|
||||||
assert(Cansave < NWindows - 2);
|
assert(Cansave < NWindows - 2);
|
||||||
|
@ -440,16 +537,70 @@ decode OP default Unknown::unknown()
|
||||||
Otherwin = Otherwin - 1;
|
Otherwin = Otherwin - 1;
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
0x32: Priv::wrpr({{
|
0x32: decode RD {
|
||||||
// XXX Need to protect with format that traps non-priv
|
0x00: Priv::wrprtpc({{
|
||||||
// access
|
if(Tl == 0)
|
||||||
xc->setMiscRegWithEffect(RD + PrStart, Rs1 ^ Rs2_or_imm13);
|
return new IllegalInstruction;
|
||||||
}});
|
else
|
||||||
0x33: HPriv::wrhpr({{
|
Tpc = Rs1 ^ Rs2_or_imm13;
|
||||||
// XXX Need to protect with format that traps non-priv/priv
|
}});
|
||||||
// access
|
0x01: Priv::wrprtnpc({{
|
||||||
xc->setMiscRegWithEffect(RD + HprStart, Rs1 ^ Rs2_or_imm13);
|
if(Tl == 0)
|
||||||
}});
|
return new IllegalInstruction;
|
||||||
|
else
|
||||||
|
Tnpc = Rs1 ^ Rs2_or_imm13;
|
||||||
|
}});
|
||||||
|
0x02: Priv::wrprtstate({{
|
||||||
|
if(Tl == 0)
|
||||||
|
return new IllegalInstruction;
|
||||||
|
else
|
||||||
|
Tstate = Rs1 ^ Rs2_or_imm13;
|
||||||
|
}});
|
||||||
|
0x03: Priv::wrprtt({{
|
||||||
|
if(Tl == 0)
|
||||||
|
return new IllegalInstruction;
|
||||||
|
else
|
||||||
|
Tt = Rs1 ^ Rs2_or_imm13;
|
||||||
|
}});
|
||||||
|
0x04: HPriv::wrprtick({{Tick = Rs1 ^ Rs2_or_imm13;}});
|
||||||
|
0x05: Priv::wrprtba({{Tba = Rs1 ^ Rs2_or_imm13;}});
|
||||||
|
0x06: Priv::wrprpstate({{Pstate = Rs1 ^ Rs2_or_imm13;}});
|
||||||
|
0x07: Priv::wrprtl({{
|
||||||
|
if(Pstate<2:> && !Hpstate<2:>)
|
||||||
|
Tl = std::min<uint64_t>(Rs1 ^ Rs2_or_imm13, MaxPTL);
|
||||||
|
else
|
||||||
|
Tl = std::min<uint64_t>(Rs1 ^ Rs2_or_imm13, MaxTL);
|
||||||
|
}});
|
||||||
|
0x08: Priv::wrprpil({{Pil = Rs1 ^ Rs2_or_imm13;}});
|
||||||
|
0x09: Priv::wrprcwp({{Cwp = Rs1 ^ Rs2_or_imm13;}});
|
||||||
|
0x0A: Priv::wrprcansave({{Cansave = Rs1 ^ Rs2_or_imm13;}});
|
||||||
|
0x0B: Priv::wrprcanrestore({{Canrestore = Rs1 ^ Rs2_or_imm13;}});
|
||||||
|
0x0C: Priv::wrprcleanwin({{Cleanwin = Rs1 ^ Rs2_or_imm13;}});
|
||||||
|
0x0D: Priv::wrprotherwin({{Otherwin = Rs1 ^ Rs2_or_imm13;}});
|
||||||
|
0x0E: Priv::wrprwstate({{Wstate = Rs1 ^ Rs2_or_imm13;}});
|
||||||
|
//0x0F should cause an illegal instruction exception
|
||||||
|
0x10: Priv::wrprgl({{
|
||||||
|
if(Pstate<2:> && !Hpstate<2:>)
|
||||||
|
Gl = std::min<uint64_t>(Rs1 ^ Rs2_or_imm13, MaxPGL);
|
||||||
|
else
|
||||||
|
Gl = std::min<uint64_t>(Rs1 ^ Rs2_or_imm13, MaxGL);
|
||||||
|
}});
|
||||||
|
//0x11-0x1F should cause an illegal instruction exception
|
||||||
|
}
|
||||||
|
0x33: decode RD {
|
||||||
|
0x00: HPriv::wrhprhpstate({{Hpstate = Rs1 ^ Rs2_or_imm13;}});
|
||||||
|
0x01: HPriv::wrhprhtstate({{
|
||||||
|
if(Tl == 0)
|
||||||
|
return new IllegalInstruction;
|
||||||
|
Htstate = Rs1 ^ Rs2_or_imm13;
|
||||||
|
}});
|
||||||
|
//0x02 should cause an illegal instruction exception
|
||||||
|
0x03: HPriv::wrhprhintp({{Hintp = Rs1 ^ Rs2_or_imm13;}});
|
||||||
|
//0x04 should cause an illegal instruction exception
|
||||||
|
0x05: HPriv::wrhprhtba({{Htba = Rs1 ^ Rs2_or_imm13;}});
|
||||||
|
//0x06-0x01D should cause an illegal instruction exception
|
||||||
|
0x1F: HPriv::wrhprhstick_cmpr({{HstickCmpr = Rs1 ^ Rs2_or_imm13;}});
|
||||||
|
}
|
||||||
0x34: decode OPF{
|
0x34: decode OPF{
|
||||||
format BasicOperate{
|
format BasicOperate{
|
||||||
0x01: fmovs({{
|
0x01: fmovs({{
|
||||||
|
|
|
@ -119,18 +119,34 @@ let {{
|
||||||
return (header_output, decoder_output, exec_output, decode_block)
|
return (header_output, decoder_output, exec_output, decode_block)
|
||||||
}};
|
}};
|
||||||
|
|
||||||
// Primary format for integer operate instructions:
|
|
||||||
def format Priv(code, *opt_flags) {{
|
def format Priv(code, *opt_flags) {{
|
||||||
checkCode = "!(Pstate<2:2> || Hpstate<2:2>)"
|
checkCode = "!(Pstate<2:> || Hpstate<2:>)"
|
||||||
(header_output, decoder_output,
|
(header_output, decoder_output,
|
||||||
exec_output, decode_block) = doPrivFormat(code,
|
exec_output, decode_block) = doPrivFormat(code,
|
||||||
checkCode, name, Name, opt_flags + ('IprAccessOp',))
|
checkCode, name, Name, opt_flags)
|
||||||
|
}};
|
||||||
|
|
||||||
|
def format NoPriv(code, *opt_flags) {{
|
||||||
|
#Instructions which use this format don't really check for
|
||||||
|
#any particular mode, but the disassembly is performed
|
||||||
|
#using the control registers actual name
|
||||||
|
checkCode = "false"
|
||||||
|
(header_output, decoder_output,
|
||||||
|
exec_output, decode_block) = doPrivFormat(code,
|
||||||
|
checkCode, name, Name, opt_flags)
|
||||||
|
}};
|
||||||
|
|
||||||
|
def format PrivCheck(code, extraCheckCode, *opt_flags) {{
|
||||||
|
checkCode = "(%s) && !(Pstate<2:> || Hpstate<2:>)" % extraCheckCode
|
||||||
|
(header_output, decoder_output,
|
||||||
|
exec_output, decode_block) = doPrivFormat(code,
|
||||||
|
checkCode, name, Name, opt_flags)
|
||||||
}};
|
}};
|
||||||
|
|
||||||
def format HPriv(code, *opt_flags) {{
|
def format HPriv(code, *opt_flags) {{
|
||||||
checkCode = "!Hpstate<2:2>"
|
checkCode = "!Hpstate<2:2>"
|
||||||
(header_output, decoder_output,
|
(header_output, decoder_output,
|
||||||
exec_output, decode_block) = doPrivFormat(code,
|
exec_output, decode_block) = doPrivFormat(code,
|
||||||
checkCode, name, Name, opt_flags + ('IprAccessOp',))
|
checkCode, name, Name, opt_flags)
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,7 @@ output decoder {{
|
||||||
#if defined(linux)
|
#if defined(linux)
|
||||||
#include <fenv.h>
|
#include <fenv.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
using namespace SparcISA;
|
using namespace SparcISA;
|
||||||
}};
|
}};
|
||||||
|
|
|
@ -80,8 +80,6 @@ def operands {{
|
||||||
'Frs2': ('FloatReg', 'df', 'dfpr(RS2)', 'IsFloating', 12),
|
'Frs2': ('FloatReg', 'df', 'dfpr(RS2)', 'IsFloating', 12),
|
||||||
'NPC': ('NPC', 'udw', None, ( None, None, 'IsControl' ), 31),
|
'NPC': ('NPC', 'udw', None, ( None, None, 'IsControl' ), 31),
|
||||||
'NNPC': ('NNPC', 'udw', None, (None, None, 'IsControl' ), 32),
|
'NNPC': ('NNPC', 'udw', None, (None, None, 'IsControl' ), 32),
|
||||||
#'Runiq': ('ControlReg', 'uq', 'Uniq', None, 1),
|
|
||||||
#'FPCR': ('ControlReg', 'uq', 'Fpcr', None, 1),
|
|
||||||
'R0': ('IntReg', 'udw', '0', None, 6),
|
'R0': ('IntReg', 'udw', '0', None, 6),
|
||||||
'R1': ('IntReg', 'udw', '1', None, 7),
|
'R1': ('IntReg', 'udw', '1', None, 7),
|
||||||
'R15': ('IntReg', 'udw', '15', 'IsInteger', 8),
|
'R15': ('IntReg', 'udw', '15', 'IsInteger', 8),
|
||||||
|
@ -91,24 +89,42 @@ def operands {{
|
||||||
'Y': ('ControlReg', 'udw', 'MISCREG_Y', None, 40),
|
'Y': ('ControlReg', 'udw', 'MISCREG_Y', None, 40),
|
||||||
'Ccr': ('ControlReg', 'udw', 'MISCREG_CCR', None, 41),
|
'Ccr': ('ControlReg', 'udw', 'MISCREG_CCR', None, 41),
|
||||||
'Asi': ('ControlReg', 'udw', 'MISCREG_ASI', None, 42),
|
'Asi': ('ControlReg', 'udw', 'MISCREG_ASI', None, 42),
|
||||||
|
'Fprs': ('ControlReg', 'udw', 'MISCREG_FPRS', None, 43),
|
||||||
|
'Pcr': ('ControlReg', 'udw', 'MISCREG_PCR', None, 44),
|
||||||
|
'Pic': ('ControlReg', 'udw', 'MISCREG_PIC', None, 45),
|
||||||
|
'Gsr': ('ControlReg', 'udw', 'MISCREG_GSR', None, 46),
|
||||||
|
'Softint': ('ControlReg', 'udw', 'MISCREG_SOFTINT', None, 47),
|
||||||
|
'SoftintSet': ('ControlReg', 'udw', 'MISCREG_SOFTINT_SET', None, 48),
|
||||||
|
'SoftintClr': ('ControlReg', 'udw', 'MISCREG_SOFTINT_CLR', None, 49),
|
||||||
|
'TickCmpr': ('ControlReg', 'udw', 'MISCREG_TICK_CMPR', None, 50),
|
||||||
|
'Stick': ('ControlReg', 'udw', 'MISCREG_STICK', None, 51),
|
||||||
|
'StickCmpr': ('ControlReg', 'udw', 'MISCREG_STICK_CMPR', None, 52),
|
||||||
|
|
||||||
'Tpc': ('ControlReg', 'udw', 'MISCREG_TPC', None, 43),
|
'Tpc': ('ControlReg', 'udw', 'MISCREG_TPC', None, 53),
|
||||||
'Tnpc': ('ControlReg', 'udw', 'MISCREG_TNPC', None, 44),
|
'Tnpc': ('ControlReg', 'udw', 'MISCREG_TNPC', None, 54),
|
||||||
'Tstate': ('ControlReg', 'udw', 'MISCREG_TSTATE', None, 45),
|
'Tstate': ('ControlReg', 'udw', 'MISCREG_TSTATE', None, 55),
|
||||||
'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 46),
|
'Tt': ('ControlReg', 'udw', 'MISCREG_TT', None, 56),
|
||||||
'Hpstate': ('ControlReg', 'udw', 'MISCREG_HPSTATE', None, 47),
|
'Tick': ('ControlReg', 'udw', 'MISCREG_TICK', None, 57),
|
||||||
'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 48),
|
'Tba': ('ControlReg', 'udw', 'MISCREG_TBA', None, 58),
|
||||||
|
'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 59),
|
||||||
|
'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 60),
|
||||||
|
'Pil': ('ControlReg', 'udw', 'MISCREG_PIL', None, 61),
|
||||||
|
'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', None, 62),
|
||||||
|
'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 63),
|
||||||
|
'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 64),
|
||||||
|
'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 65),
|
||||||
|
'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 66),
|
||||||
|
'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 67),
|
||||||
|
'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 68),
|
||||||
|
|
||||||
'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', None, 49),
|
'Hpstate': ('ControlReg', 'udw', 'MISCREG_HPSTATE', None, 69),
|
||||||
'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 50),
|
'Htstate': ('ControlReg', 'udw', 'MISCREG_HTSTATE', None, 70),
|
||||||
'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 51),
|
'Hintp': ('ControlReg', 'udw', 'MISCREG_HINTP', None, 71),
|
||||||
'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 52),
|
'Htba': ('ControlReg', 'udw', 'MISCREG_HTBA', None, 72),
|
||||||
'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 53),
|
'HstickCmpr': ('ControlReg', 'udw', 'MISCREG_HSTICK_CMPR', None, 73),
|
||||||
'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 54),
|
'Hver': ('ControlReg', 'udw', 'MISCREG_HVER', None, 74),
|
||||||
'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 55),
|
|
||||||
|
|
||||||
'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 56),
|
'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 80),
|
||||||
'Gsr': ('ControlReg', 'udw', 'MISCREG_GSR', None, 57),
|
|
||||||
# Mem gets a large number so it's always last
|
# Mem gets a large number so it's always last
|
||||||
'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 100)
|
'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 100)
|
||||||
|
|
||||||
|
|
57
src/arch/sparc/kernel_stats.hh
Normal file
57
src/arch/sparc/kernel_stats.hh
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2004-2005 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Gabe Black
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ARCH_SPARC_KERNEL_STATS_HH__
|
||||||
|
#define __ARCH_SPARC_KERNEL_STATS_HH__
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <stack>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "kern/kernel_stats.hh"
|
||||||
|
|
||||||
|
namespace SparcISA {
|
||||||
|
namespace Kernel {
|
||||||
|
|
||||||
|
enum cpu_mode { hypervisor, kernel, user, idle, cpu_mode_num };
|
||||||
|
extern const char *modestr[];
|
||||||
|
|
||||||
|
class Statistics : public ::Kernel::Statistics
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Statistics(System *system) : ::Kernel::Statistics(system)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* end namespace AlphaISA::Kernel */
|
||||||
|
} /* end namespace AlphaISA */
|
||||||
|
|
||||||
|
#endif // __ARCH_SPARC_KERNEL_STATS_HH__
|
|
@ -29,11 +29,18 @@
|
||||||
* Ali Saidi
|
* Ali Saidi
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "arch/sparc/asi.hh"
|
||||||
#include "arch/sparc/miscregfile.hh"
|
#include "arch/sparc/miscregfile.hh"
|
||||||
|
#include "base/bitfield.hh"
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
|
#include "config/full_system.hh"
|
||||||
#include "cpu/base.hh"
|
#include "cpu/base.hh"
|
||||||
#include "cpu/thread_context.hh"
|
#include "cpu/thread_context.hh"
|
||||||
|
|
||||||
|
#if FULL_SYSTEM
|
||||||
|
#include "arch/sparc/system.hh"
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace SparcISA;
|
using namespace SparcISA;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -55,66 +62,41 @@ string SparcISA::getMiscRegName(RegIndex index)
|
||||||
return miscRegName[index];
|
return miscRegName[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
|
||||||
|
|
||||||
//XXX These need an implementation someplace
|
|
||||||
/** Fullsystem only register version of ReadRegWithEffect() */
|
|
||||||
MiscReg MiscRegFile::readFSRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc);
|
|
||||||
/** Fullsystem only register version of SetRegWithEffect() */
|
|
||||||
Fault MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val,
|
|
||||||
ThreadContext * tc);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void MiscRegFile::reset()
|
void MiscRegFile::reset()
|
||||||
{
|
{
|
||||||
pstateFields.pef = 0; //No FPU
|
y = 0;
|
||||||
//pstateFields.pef = 1; //FPU
|
ccr = 0;
|
||||||
#if FULL_SYSTEM
|
asi = 0;
|
||||||
//For SPARC, when a system is first started, there is a power
|
tick = 0;
|
||||||
//on reset Trap which sets the processor into the following state.
|
fprs = 0;
|
||||||
//Bits that aren't set aren't defined on startup.
|
gsr = 0;
|
||||||
tl = MaxTL;
|
softint = 0;
|
||||||
gl = MaxGL;
|
tick_cmpr = 0;
|
||||||
|
stick = 0;
|
||||||
tickFields.counter = 0; //The TICK register is unreadable bya
|
stick_cmpr = 0;
|
||||||
tickFields.npt = 1; //The TICK register is unreadable by by !priv
|
memset(tpc, 0, sizeof(tpc));
|
||||||
|
memset(tnpc, 0, sizeof(tnpc));
|
||||||
softint = 0; // Clear all the soft interrupt bits
|
memset(tstate, 0, sizeof(tstate));
|
||||||
tick_cmprFields.int_dis = 1; // disable timer compare interrupts
|
memset(tt, 0, sizeof(tt));
|
||||||
tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
|
pstate = 0;
|
||||||
stickFields.npt = 1; //The TICK register is unreadable by by !priv
|
tl = 0;
|
||||||
stick_cmprFields.int_dis = 1; // disable timer compare interrupts
|
pil = 0;
|
||||||
stick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
|
cwp = 0;
|
||||||
|
cansave = 0;
|
||||||
|
canrestore = 0;
|
||||||
tt[tl] = power_on_reset;
|
cleanwin = 0;
|
||||||
pstate = 0; // fields 0 but pef
|
otherwin = 0;
|
||||||
pstateFields.pef = 1;
|
wstate = 0;
|
||||||
|
gl = 0;
|
||||||
hpstate = 0;
|
hpstate = 0;
|
||||||
hpstateFields.red = 1;
|
memset(htstate, 0, sizeof(htstate));
|
||||||
hpstateFields.hpriv = 1;
|
hintp = 0;
|
||||||
hpstateFields.tlz = 0; // this is a guess
|
htba = 0;
|
||||||
hintp = 0; // no interrupts pending
|
hstick_cmpr = 0;
|
||||||
hstick_cmprFields.int_dis = 1; // disable timer compare interrupts
|
strandStatusReg = 0;
|
||||||
hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
|
fsr = 0;
|
||||||
#else
|
implicitInstAsi = ASI_PRIMARY;
|
||||||
/* //This sets up the initial state of the processor for usermode processes
|
implicitDataAsi = ASI_PRIMARY;
|
||||||
pstateFields.priv = 0; //Process runs in user mode
|
|
||||||
pstateFields.ie = 1; //Interrupts are enabled
|
|
||||||
fsrFields.rd = 0; //Round to nearest
|
|
||||||
fsrFields.tem = 0; //Floating point traps not enabled
|
|
||||||
fsrFields.ns = 0; //Non standard mode off
|
|
||||||
fsrFields.qne = 0; //Floating point queue is empty
|
|
||||||
fsrFields.aexc = 0; //No accrued exceptions
|
|
||||||
fsrFields.cexc = 0; //No current exceptions
|
|
||||||
|
|
||||||
//Register window management registers
|
|
||||||
otherwin = 0; //No windows contain info from other programs
|
|
||||||
canrestore = 0; //There are no windows to pop
|
|
||||||
cansave = MaxTL - 2; //All windows are available to save into
|
|
||||||
cleanwin = MaxTL;*/
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MiscReg MiscRegFile::readReg(int miscReg)
|
MiscReg MiscRegFile::readReg(int miscReg)
|
||||||
|
@ -131,8 +113,9 @@ MiscReg MiscRegFile::readReg(int miscReg)
|
||||||
case MISCREG_TICK:
|
case MISCREG_TICK:
|
||||||
return tick;
|
return tick;
|
||||||
case MISCREG_PCR:
|
case MISCREG_PCR:
|
||||||
|
panic("PCR not implemented\n");
|
||||||
case MISCREG_PIC:
|
case MISCREG_PIC:
|
||||||
panic("ASR number %d not implemented\n", miscReg - AsrStart);
|
panic("PIC not implemented\n");
|
||||||
case MISCREG_GSR:
|
case MISCREG_GSR:
|
||||||
return gsr;
|
return gsr;
|
||||||
case MISCREG_SOFTINT:
|
case MISCREG_SOFTINT:
|
||||||
|
@ -207,17 +190,27 @@ MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc)
|
||||||
switch (miscReg) {
|
switch (miscReg) {
|
||||||
case MISCREG_TICK:
|
case MISCREG_TICK:
|
||||||
case MISCREG_PRIVTICK:
|
case MISCREG_PRIVTICK:
|
||||||
return tc->getCpuPtr()->curCycle() - tickFields.counter |
|
return tc->getCpuPtr()->curCycle() - (tick & mask(63)) |
|
||||||
tickFields.npt << 63;
|
(tick & ~(mask(63))) << 63;
|
||||||
case MISCREG_FPRS:
|
case MISCREG_FPRS:
|
||||||
panic("FPU not implemented\n");
|
panic("FPU not implemented\n");
|
||||||
case MISCREG_PCR:
|
case MISCREG_PCR:
|
||||||
case MISCREG_PIC:
|
case MISCREG_PIC:
|
||||||
panic("Performance Instrumentation not impl\n");
|
panic("Performance Instrumentation not impl\n");
|
||||||
|
|
||||||
/** Floating Point Status Register */
|
/** Floating Point Status Register */
|
||||||
case MISCREG_FSR:
|
case MISCREG_FSR:
|
||||||
panic("Floating Point not implemented\n");
|
panic("Floating Point not implemented\n");
|
||||||
|
//We'll include this only in FS so we don't need the SparcSystem type around
|
||||||
|
//in SE.
|
||||||
|
#if FULL_SYSTEM
|
||||||
|
case MISCREG_STICK:
|
||||||
|
SparcSystem *sys;
|
||||||
|
sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr());
|
||||||
|
assert(sys != NULL);
|
||||||
|
return curTick/Clock::Int::ns - sys->sysTick | (stick & ~(mask(63)));
|
||||||
|
#endif
|
||||||
|
case MISCREG_HVER:
|
||||||
|
return NWindows | MaxTL << 8 | MaxGL << 16;
|
||||||
}
|
}
|
||||||
return readReg(miscReg);
|
return readReg(miscReg);
|
||||||
}
|
}
|
||||||
|
@ -241,8 +234,9 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val)
|
||||||
tick = val;
|
tick = val;
|
||||||
break;
|
break;
|
||||||
case MISCREG_PCR:
|
case MISCREG_PCR:
|
||||||
|
panic("PCR not implemented\n");
|
||||||
case MISCREG_PIC:
|
case MISCREG_PIC:
|
||||||
panic("ASR number %d not implemented\n", miscReg - AsrStart);
|
panic("PIC not implemented\n");
|
||||||
case MISCREG_GSR:
|
case MISCREG_GSR:
|
||||||
gsr = val;
|
gsr = val;
|
||||||
break;
|
break;
|
||||||
|
@ -337,14 +331,42 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void MiscRegFile::setImplicitAsis()
|
||||||
|
{
|
||||||
|
//The spec seems to use trap level to indicate the privilege level of the
|
||||||
|
//processor. It's unclear whether the implicit ASIs should directly depend
|
||||||
|
//on the trap level, or if they should really be based on the privelege
|
||||||
|
//bits
|
||||||
|
if(tl == 0)
|
||||||
|
{
|
||||||
|
implicitInstAsi = implicitDataAsi =
|
||||||
|
(pstate & (1 << 9)) ? ASI_PRIMARY_LITTLE : ASI_PRIMARY;
|
||||||
|
}
|
||||||
|
else if(tl <= MaxPTL)
|
||||||
|
{
|
||||||
|
implicitInstAsi = ASI_NUCLEUS;
|
||||||
|
implicitDataAsi = (pstate & (1 << 9)) ? ASI_NUCLEUS_LITTLE : ASI_NUCLEUS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//This is supposed to force physical addresses to match the spec.
|
||||||
|
//It might not because of context values and partition values.
|
||||||
|
implicitInstAsi = implicitDataAsi = ASI_REAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MiscRegFile::setRegWithEffect(int miscReg,
|
void MiscRegFile::setRegWithEffect(int miscReg,
|
||||||
const MiscReg &val, ThreadContext * tc)
|
const MiscReg &val, ThreadContext * tc)
|
||||||
{
|
{
|
||||||
const uint64_t Bit64 = (1ULL << 63);
|
const uint64_t Bit64 = (1ULL << 63);
|
||||||
|
#if FULL_SYSTEM
|
||||||
|
uint64_t time;
|
||||||
|
SparcSystem *sys;
|
||||||
|
#endif
|
||||||
switch (miscReg) {
|
switch (miscReg) {
|
||||||
case MISCREG_TICK:
|
case MISCREG_TICK:
|
||||||
tickFields.counter = tc->getCpuPtr()->curCycle() - val & ~Bit64;
|
tick = tc->getCpuPtr()->curCycle() - val & ~Bit64;
|
||||||
tickFields.npt = val & Bit64 ? 1 : 0;
|
tick |= val & Bit64;
|
||||||
break;
|
break;
|
||||||
case MISCREG_FPRS:
|
case MISCREG_FPRS:
|
||||||
//Configure the fpu based on the fprs
|
//Configure the fpu based on the fprs
|
||||||
|
@ -352,12 +374,84 @@ void MiscRegFile::setRegWithEffect(int miscReg,
|
||||||
case MISCREG_PCR:
|
case MISCREG_PCR:
|
||||||
//Set up performance counting based on pcr value
|
//Set up performance counting based on pcr value
|
||||||
break;
|
break;
|
||||||
|
case MISCREG_PSTATE:
|
||||||
|
pstate = val;
|
||||||
|
setImplicitAsis();
|
||||||
|
return;
|
||||||
|
case MISCREG_TL:
|
||||||
|
tl = val;
|
||||||
|
setImplicitAsis();
|
||||||
|
return;
|
||||||
case MISCREG_CWP:
|
case MISCREG_CWP:
|
||||||
tc->changeRegFileContext(CONTEXT_CWP, val);
|
tc->changeRegFileContext(CONTEXT_CWP, val);
|
||||||
break;
|
break;
|
||||||
case MISCREG_GL:
|
case MISCREG_GL:
|
||||||
tc->changeRegFileContext(CONTEXT_GLOBALS, val);
|
tc->changeRegFileContext(CONTEXT_GLOBALS, val);
|
||||||
break;
|
break;
|
||||||
|
case MISCREG_SOFTINT:
|
||||||
|
//We need to inject interrupts, and or notify the interrupt
|
||||||
|
//object that it needs to use a different interrupt level.
|
||||||
|
//Any newly appropriate interrupts will happen when the cpu gets
|
||||||
|
//around to checking for them. This might not be quite what we
|
||||||
|
//want.
|
||||||
|
break;
|
||||||
|
case MISCREG_SOFTINT_CLR:
|
||||||
|
//Do whatever this is supposed to do...
|
||||||
|
break;
|
||||||
|
case MISCREG_SOFTINT_SET:
|
||||||
|
//Do whatever this is supposed to do...
|
||||||
|
break;
|
||||||
|
#if FULL_SYSTEM
|
||||||
|
case MISCREG_TICK_CMPR:
|
||||||
|
if (tickCompare == NULL)
|
||||||
|
tickCompare = new TickCompareEvent(this, tc);
|
||||||
|
setReg(miscReg, val);
|
||||||
|
if ((tick_cmpr & mask(63)) && tickCompare->scheduled())
|
||||||
|
tickCompare->deschedule();
|
||||||
|
time = (tick_cmpr & mask(63)) - (tick & mask(63));
|
||||||
|
if (!(tick_cmpr & ~mask(63)) && time > 0)
|
||||||
|
tickCompare->schedule(time * tc->getCpuPtr()->cycles(1));
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case MISCREG_PIL:
|
||||||
|
//We need to inject interrupts, and or notify the interrupt
|
||||||
|
//object that it needs to use a different interrupt level.
|
||||||
|
//Any newly appropriate interrupts will happen when the cpu gets
|
||||||
|
//around to checking for them. This might not be quite what we
|
||||||
|
//want.
|
||||||
|
break;
|
||||||
|
//We'll include this only in FS so we don't need the SparcSystem type around
|
||||||
|
//in SE.
|
||||||
|
#if FULL_SYSTEM
|
||||||
|
case MISCREG_STICK:
|
||||||
|
sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr());
|
||||||
|
assert(sys != NULL);
|
||||||
|
sys->sysTick = curTick/Clock::Int::ns - val & ~Bit64;
|
||||||
|
stick |= val & Bit64;
|
||||||
|
break;
|
||||||
|
case MISCREG_STICK_CMPR:
|
||||||
|
if (sTickCompare == NULL)
|
||||||
|
sTickCompare = new STickCompareEvent(this, tc);
|
||||||
|
sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr());
|
||||||
|
assert(sys != NULL);
|
||||||
|
if ((stick_cmpr & ~mask(63)) && sTickCompare->scheduled())
|
||||||
|
sTickCompare->deschedule();
|
||||||
|
time = (stick_cmpr & mask(63)) - sys->sysTick;
|
||||||
|
if (!(stick_cmpr & ~mask(63)) && time > 0)
|
||||||
|
sTickCompare->schedule(time * Clock::Int::ns);
|
||||||
|
break;
|
||||||
|
case MISCREG_HSTICK_CMPR:
|
||||||
|
if (hSTickCompare == NULL)
|
||||||
|
hSTickCompare = new HSTickCompareEvent(this, tc);
|
||||||
|
sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr());
|
||||||
|
assert(sys != NULL);
|
||||||
|
if ((hstick_cmpr & ~mask(63)) && hSTickCompare->scheduled())
|
||||||
|
hSTickCompare->deschedule();
|
||||||
|
int64_t time = (hstick_cmpr & mask(63)) - sys->sysTick;
|
||||||
|
if (!(hstick_cmpr & ~mask(63)) && time > 0)
|
||||||
|
hSTickCompare->schedule(time * Clock::Int::ns);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
setReg(miscReg, val);
|
setReg(miscReg, val);
|
||||||
}
|
}
|
||||||
|
@ -389,6 +483,8 @@ void MiscRegFile::serialize(std::ostream & os)
|
||||||
SERIALIZE_ARRAY(htstate, MaxTL);
|
SERIALIZE_ARRAY(htstate, MaxTL);
|
||||||
SERIALIZE_SCALAR(htba);
|
SERIALIZE_SCALAR(htba);
|
||||||
SERIALIZE_SCALAR(hstick_cmpr);
|
SERIALIZE_SCALAR(hstick_cmpr);
|
||||||
|
SERIALIZE_SCALAR((int)implicitInstAsi);
|
||||||
|
SERIALIZE_SCALAR((int)implicitDataAsi);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section)
|
void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section)
|
||||||
|
@ -418,5 +514,29 @@ void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section)
|
||||||
UNSERIALIZE_ARRAY(htstate, MaxTL);
|
UNSERIALIZE_ARRAY(htstate, MaxTL);
|
||||||
UNSERIALIZE_SCALAR(htba);
|
UNSERIALIZE_SCALAR(htba);
|
||||||
UNSERIALIZE_SCALAR(hstick_cmpr);
|
UNSERIALIZE_SCALAR(hstick_cmpr);
|
||||||
|
int temp;
|
||||||
|
UNSERIALIZE_SCALAR(temp);
|
||||||
|
implicitInstAsi = (ASI)temp;
|
||||||
|
UNSERIALIZE_SCALAR(temp);
|
||||||
|
implicitDataAsi = (ASI)temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if FULL_SYSTEM
|
||||||
|
void
|
||||||
|
MiscRegFile::processTickCompare(ThreadContext *tc)
|
||||||
|
{
|
||||||
|
panic("tick compare not implemented\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MiscRegFile::processSTickCompare(ThreadContext *tc)
|
||||||
|
{
|
||||||
|
panic("tick compare not implemented\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MiscRegFile::processHSTickCompare(ThreadContext *tc)
|
||||||
|
{
|
||||||
|
panic("tick compare not implemented\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -32,9 +32,11 @@
|
||||||
#ifndef __ARCH_SPARC_MISCREGFILE_HH__
|
#ifndef __ARCH_SPARC_MISCREGFILE_HH__
|
||||||
#define __ARCH_SPARC_MISCREGFILE_HH__
|
#define __ARCH_SPARC_MISCREGFILE_HH__
|
||||||
|
|
||||||
|
#include "arch/sparc/asi.hh"
|
||||||
#include "arch/sparc/faults.hh"
|
#include "arch/sparc/faults.hh"
|
||||||
#include "arch/sparc/isa_traits.hh"
|
#include "arch/sparc/isa_traits.hh"
|
||||||
#include "arch/sparc/types.hh"
|
#include "arch/sparc/types.hh"
|
||||||
|
#include "cpu/cpuevent.hh"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -44,59 +46,53 @@ namespace SparcISA
|
||||||
//These functions map register indices to names
|
//These functions map register indices to names
|
||||||
std::string getMiscRegName(RegIndex);
|
std::string getMiscRegName(RegIndex);
|
||||||
|
|
||||||
const int AsrStart = 0;
|
|
||||||
const int PrStart = 32;
|
|
||||||
const int HprStart = 64;
|
|
||||||
const int MiscStart = 96;
|
|
||||||
|
|
||||||
enum MiscRegIndex
|
enum MiscRegIndex
|
||||||
{
|
{
|
||||||
/** Ancillary State Registers */
|
/** Ancillary State Registers */
|
||||||
MISCREG_Y = AsrStart + 0,
|
MISCREG_Y,
|
||||||
MISCREG_CCR = AsrStart + 2,
|
MISCREG_CCR,
|
||||||
MISCREG_ASI = AsrStart + 3,
|
MISCREG_ASI,
|
||||||
MISCREG_TICK = AsrStart + 4,
|
MISCREG_TICK,
|
||||||
MISCREG_FPRS = AsrStart + 6,
|
MISCREG_FPRS,
|
||||||
MISCREG_PCR = AsrStart + 16,
|
MISCREG_PCR,
|
||||||
MISCREG_PIC = AsrStart + 17,
|
MISCREG_PIC,
|
||||||
MISCREG_GSR = AsrStart + 19,
|
MISCREG_GSR,
|
||||||
MISCREG_SOFTINT_SET = AsrStart + 20,
|
MISCREG_SOFTINT_SET,
|
||||||
MISCREG_SOFTINT_CLR = AsrStart + 21,
|
MISCREG_SOFTINT_CLR,
|
||||||
MISCREG_SOFTINT = AsrStart + 22,
|
MISCREG_SOFTINT,
|
||||||
MISCREG_TICK_CMPR = AsrStart + 23,
|
MISCREG_TICK_CMPR,
|
||||||
MISCREG_STICK = AsrStart + 24,
|
MISCREG_STICK,
|
||||||
MISCREG_STICK_CMPR = AsrStart + 25,
|
MISCREG_STICK_CMPR,
|
||||||
|
|
||||||
/** Privilged Registers */
|
/** Privilged Registers */
|
||||||
MISCREG_TPC = PrStart + 0,
|
MISCREG_TPC,
|
||||||
MISCREG_TNPC = PrStart + 1,
|
MISCREG_TNPC,
|
||||||
MISCREG_TSTATE = PrStart + 2,
|
MISCREG_TSTATE,
|
||||||
MISCREG_TT = PrStart + 3,
|
MISCREG_TT,
|
||||||
MISCREG_PRIVTICK = PrStart + 4,
|
MISCREG_PRIVTICK,
|
||||||
MISCREG_TBA = PrStart + 5,
|
MISCREG_TBA,
|
||||||
MISCREG_PSTATE = PrStart + 6,
|
MISCREG_PSTATE,
|
||||||
MISCREG_TL = PrStart + 7,
|
MISCREG_TL,
|
||||||
MISCREG_PIL = PrStart + 8,
|
MISCREG_PIL,
|
||||||
MISCREG_CWP = PrStart + 9,
|
MISCREG_CWP,
|
||||||
MISCREG_CANSAVE = PrStart + 10,
|
MISCREG_CANSAVE,
|
||||||
MISCREG_CANRESTORE = PrStart + 11,
|
MISCREG_CANRESTORE,
|
||||||
MISCREG_CLEANWIN = PrStart + 12,
|
MISCREG_CLEANWIN,
|
||||||
MISCREG_OTHERWIN = PrStart + 13,
|
MISCREG_OTHERWIN,
|
||||||
MISCREG_WSTATE = PrStart + 14,
|
MISCREG_WSTATE,
|
||||||
MISCREG_GL = PrStart + 16,
|
MISCREG_GL,
|
||||||
|
|
||||||
/** Hyper privileged registers */
|
/** Hyper privileged registers */
|
||||||
MISCREG_HPSTATE = HprStart + 0,
|
MISCREG_HPSTATE,
|
||||||
MISCREG_HTSTATE = HprStart + 1,
|
MISCREG_HTSTATE,
|
||||||
MISCREG_HINTP = HprStart + 3,
|
MISCREG_HINTP,
|
||||||
MISCREG_HTBA = HprStart + 5,
|
MISCREG_HTBA,
|
||||||
MISCREG_HVER = HprStart + 6,
|
MISCREG_HVER,
|
||||||
MISCREG_STRAND_STS_REG = HprStart + 16,
|
MISCREG_STRAND_STS_REG,
|
||||||
MISCREG_HSTICK_CMPR = HprStart + 31,
|
MISCREG_HSTICK_CMPR,
|
||||||
|
|
||||||
/** Floating Point Status Register */
|
/** Floating Point Status Register */
|
||||||
MISCREG_FSR = MiscStart + 0
|
MISCREG_FSR
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// The control registers, broken out into fields
|
// The control registers, broken out into fields
|
||||||
|
@ -105,93 +101,16 @@ namespace SparcISA
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/* ASR Registers */
|
/* ASR Registers */
|
||||||
union {
|
uint64_t y; // Y (used in obsolete multiplication)
|
||||||
uint64_t y; // Y (used in obsolete multiplication)
|
uint8_t ccr; // Condition Code Register
|
||||||
struct {
|
|
||||||
uint64_t value:32; // The actual value stored in y
|
|
||||||
uint64_t :32; // reserved bits
|
|
||||||
} yFields;
|
|
||||||
};
|
|
||||||
union {
|
|
||||||
uint8_t ccr; // Condition Code Register
|
|
||||||
struct {
|
|
||||||
union {
|
|
||||||
uint8_t icc:4; // 32-bit condition codes
|
|
||||||
struct {
|
|
||||||
uint8_t c:1; // Carry
|
|
||||||
uint8_t v:1; // Overflow
|
|
||||||
uint8_t z:1; // Zero
|
|
||||||
uint8_t n:1; // Negative
|
|
||||||
} iccFields;
|
|
||||||
};
|
|
||||||
union {
|
|
||||||
uint8_t xcc:4; // 64-bit condition codes
|
|
||||||
struct {
|
|
||||||
uint8_t c:1; // Carry
|
|
||||||
uint8_t v:1; // Overflow
|
|
||||||
uint8_t z:1; // Zero
|
|
||||||
uint8_t n:1; // Negative
|
|
||||||
} xccFields;
|
|
||||||
};
|
|
||||||
} ccrFields;
|
|
||||||
};
|
|
||||||
uint8_t asi; // Address Space Identifier
|
uint8_t asi; // Address Space Identifier
|
||||||
union {
|
uint64_t tick; // Hardware clock-tick counter
|
||||||
uint64_t tick; // Hardware clock-tick counter
|
uint8_t fprs; // Floating-Point Register State
|
||||||
struct {
|
uint64_t gsr; // General Status Register
|
||||||
int64_t counter:63; // Clock-tick count
|
uint64_t softint;
|
||||||
uint64_t npt:1; // Non-priveleged trap
|
uint64_t tick_cmpr; // Hardware tick compare registers
|
||||||
} tickFields;
|
uint64_t stick; // Hardware clock-tick counter
|
||||||
};
|
uint64_t stick_cmpr; // Hardware tick compare registers
|
||||||
union {
|
|
||||||
uint8_t fprs; // Floating-Point Register State
|
|
||||||
struct {
|
|
||||||
uint8_t dl:1; // Dirty lower
|
|
||||||
uint8_t du:1; // Dirty upper
|
|
||||||
uint8_t fef:1; // FPRS enable floating-Point
|
|
||||||
} fprsFields;
|
|
||||||
};
|
|
||||||
union {
|
|
||||||
uint64_t gsr; //General Status Register
|
|
||||||
struct {
|
|
||||||
uint64_t mask:32;
|
|
||||||
uint64_t :4;
|
|
||||||
uint64_t im:1;
|
|
||||||
uint64_t irnd:2;
|
|
||||||
uint64_t :17;
|
|
||||||
uint64_t scale:5;
|
|
||||||
uint64_t align:3;
|
|
||||||
} gsrFields;
|
|
||||||
};
|
|
||||||
union {
|
|
||||||
uint64_t softint;
|
|
||||||
struct {
|
|
||||||
uint64_t tm:1;
|
|
||||||
uint64_t int_level:14;
|
|
||||||
uint64_t sm:1;
|
|
||||||
} softintFields;
|
|
||||||
};
|
|
||||||
union {
|
|
||||||
uint64_t tick_cmpr; // Hardware tick compare registers
|
|
||||||
struct {
|
|
||||||
uint64_t tick_cmpr:63; // Clock-tick count
|
|
||||||
uint64_t int_dis:1; // Non-priveleged trap
|
|
||||||
} tick_cmprFields;
|
|
||||||
};
|
|
||||||
union {
|
|
||||||
uint64_t stick; // Hardware clock-tick counter
|
|
||||||
struct {
|
|
||||||
int64_t :63; // Not used, storage in SparcSystem
|
|
||||||
uint64_t npt:1; // Non-priveleged trap
|
|
||||||
} stickFields;
|
|
||||||
};
|
|
||||||
union {
|
|
||||||
uint64_t stick_cmpr; // Hardware tick compare registers
|
|
||||||
struct {
|
|
||||||
uint64_t tick_cmpr:63; // Clock-tick count
|
|
||||||
uint64_t int_dis:1; // Non-priveleged trap
|
|
||||||
} stick_cmprFields;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* Privileged Registers */
|
/* Privileged Registers */
|
||||||
|
@ -199,37 +118,12 @@ namespace SparcISA
|
||||||
// previous trap level)
|
// previous trap level)
|
||||||
uint64_t tnpc[MaxTL]; // Trap Next Program Counter (value from
|
uint64_t tnpc[MaxTL]; // Trap Next Program Counter (value from
|
||||||
// previous trap level)
|
// previous trap level)
|
||||||
union {
|
uint64_t tstate[MaxTL]; // Trap State
|
||||||
uint64_t tstate[MaxTL]; // Trap State
|
|
||||||
struct {
|
|
||||||
//Values are from previous trap level
|
|
||||||
uint64_t cwp:5; // Current Window Pointer
|
|
||||||
uint64_t :3; // Reserved bits
|
|
||||||
uint64_t pstate:13; // Process State
|
|
||||||
uint64_t :3; // Reserved bits
|
|
||||||
uint64_t asi:8; // Address Space Identifier
|
|
||||||
uint64_t ccr:8; // Condition Code Register
|
|
||||||
uint64_t gl:8; // Global level
|
|
||||||
} tstateFields[MaxTL];
|
|
||||||
};
|
|
||||||
uint16_t tt[MaxTL]; // Trap Type (Type of trap which occured
|
uint16_t tt[MaxTL]; // Trap Type (Type of trap which occured
|
||||||
// on the previous level)
|
// on the previous level)
|
||||||
uint64_t tba; // Trap Base Address
|
uint64_t tba; // Trap Base Address
|
||||||
|
|
||||||
union {
|
uint16_t pstate; // Process State Register
|
||||||
uint16_t pstate; // Process State Register
|
|
||||||
struct {
|
|
||||||
uint16_t :1; // reserved
|
|
||||||
uint16_t ie:1; // Interrupt enable
|
|
||||||
uint16_t priv:1; // Privelege mode
|
|
||||||
uint16_t am:1; // Address mask
|
|
||||||
uint16_t pef:1; // PSTATE enable floating-point
|
|
||||||
uint16_t :1; // reserved2
|
|
||||||
uint16_t mm:2; // Memory Model
|
|
||||||
uint16_t tle:1; // Trap little-endian
|
|
||||||
uint16_t cle:1; // Current little-endian
|
|
||||||
} pstateFields;
|
|
||||||
};
|
|
||||||
uint8_t tl; // Trap Level
|
uint8_t tl; // Trap Level
|
||||||
uint8_t pil; // Process Interrupt Register
|
uint8_t pil; // Process Interrupt Register
|
||||||
uint8_t cwp; // Current Window Pointer
|
uint8_t cwp; // Current Window Pointer
|
||||||
|
@ -237,97 +131,23 @@ namespace SparcISA
|
||||||
uint8_t canrestore; // Restorable windows
|
uint8_t canrestore; // Restorable windows
|
||||||
uint8_t cleanwin; // Clean windows
|
uint8_t cleanwin; // Clean windows
|
||||||
uint8_t otherwin; // Other windows
|
uint8_t otherwin; // Other windows
|
||||||
union {
|
uint8_t wstate; // Window State
|
||||||
uint8_t wstate; // Window State
|
|
||||||
struct {
|
|
||||||
uint8_t normal:3; // Bits TT<4:2> are set to on a normal
|
|
||||||
// register window trap
|
|
||||||
uint8_t other:3; // Bits TT<4:2> are set to on an "otherwin"
|
|
||||||
// register window trap
|
|
||||||
} wstateFields;
|
|
||||||
};
|
|
||||||
uint8_t gl; // Global level register
|
uint8_t gl; // Global level register
|
||||||
|
|
||||||
|
|
||||||
/** Hyperprivileged Registers */
|
/** Hyperprivileged Registers */
|
||||||
union {
|
uint64_t hpstate; // Hyperprivileged State Register
|
||||||
uint64_t hpstate; // Hyperprivileged State Register
|
uint64_t htstate[MaxTL];// Hyperprivileged Trap State Register
|
||||||
struct {
|
|
||||||
uint8_t tlz: 1;
|
|
||||||
uint8_t :1;
|
|
||||||
uint8_t hpriv:1;
|
|
||||||
uint8_t :2;
|
|
||||||
uint8_t red:1;
|
|
||||||
uint8_t :4;
|
|
||||||
uint8_t ibe:1;
|
|
||||||
uint8_t id:1;
|
|
||||||
} hpstateFields;
|
|
||||||
};
|
|
||||||
|
|
||||||
uint64_t htstate[MaxTL]; // Hyperprivileged Trap State Register
|
|
||||||
uint64_t hintp;
|
uint64_t hintp;
|
||||||
uint64_t htba; // Hyperprivileged Trap Base Address register
|
uint64_t htba; // Hyperprivileged Trap Base Address register
|
||||||
union {
|
uint64_t hstick_cmpr; // Hardware tick compare registers
|
||||||
uint64_t hstick_cmpr; // Hardware tick compare registers
|
|
||||||
struct {
|
|
||||||
uint64_t tick_cmpr:63; // Clock-tick count
|
|
||||||
uint64_t int_dis:1; // Non-priveleged trap
|
|
||||||
} hstick_cmprFields;
|
|
||||||
};
|
|
||||||
|
|
||||||
uint64_t strandStatusReg; // Per strand status register
|
|
||||||
|
|
||||||
|
uint64_t strandStatusReg;// Per strand status register
|
||||||
|
|
||||||
/** Floating point misc registers. */
|
/** Floating point misc registers. */
|
||||||
union {
|
uint64_t fsr; // Floating-Point State Register
|
||||||
uint64_t fsr; // Floating-Point State Register
|
|
||||||
struct {
|
ASI implicitInstAsi;
|
||||||
union {
|
ASI implicitDataAsi;
|
||||||
uint64_t cexc:5; // Current excpetion
|
|
||||||
struct {
|
|
||||||
uint64_t nxc:1; // Inexact
|
|
||||||
uint64_t dzc:1; // Divide by zero
|
|
||||||
uint64_t ufc:1; // Underflow
|
|
||||||
uint64_t ofc:1; // Overflow
|
|
||||||
uint64_t nvc:1; // Invalid operand
|
|
||||||
} cexcFields;
|
|
||||||
};
|
|
||||||
union {
|
|
||||||
uint64_t aexc:5; // Accrued exception
|
|
||||||
struct {
|
|
||||||
uint64_t nxc:1; // Inexact
|
|
||||||
uint64_t dzc:1; // Divide by zero
|
|
||||||
uint64_t ufc:1; // Underflow
|
|
||||||
uint64_t ofc:1; // Overflow
|
|
||||||
uint64_t nvc:1; // Invalid operand
|
|
||||||
} aexcFields;
|
|
||||||
};
|
|
||||||
uint64_t fcc0:2; // Floating-Point condtion codes
|
|
||||||
uint64_t :1; // Reserved bits
|
|
||||||
uint64_t qne:1; // Deferred trap queue not empty
|
|
||||||
// with no queue, it should read 0
|
|
||||||
uint64_t ftt:3; // Floating-Point trap type
|
|
||||||
uint64_t ver:3; // Version (of the FPU)
|
|
||||||
uint64_t :2; // Reserved bits
|
|
||||||
uint64_t ns:1; // Nonstandard floating point
|
|
||||||
union {
|
|
||||||
uint64_t tem:5; // Trap Enable Mask
|
|
||||||
struct {
|
|
||||||
uint64_t nxm:1; // Inexact
|
|
||||||
uint64_t dzm:1; // Divide by zero
|
|
||||||
uint64_t ufm:1; // Underflow
|
|
||||||
uint64_t ofm:1; // Overflow
|
|
||||||
uint64_t nvm:1; // Invalid operand
|
|
||||||
} temFields;
|
|
||||||
};
|
|
||||||
uint64_t :2; // Reserved bits
|
|
||||||
uint64_t rd:2; // Rounding direction
|
|
||||||
uint64_t fcc1:2; // Floating-Point condition codes
|
|
||||||
uint64_t fcc2:2; // Floating-Point condition codes
|
|
||||||
uint64_t fcc3:2; // Floating-Point condition codes
|
|
||||||
uint64_t :26; // Reserved bits
|
|
||||||
} fsrFields;
|
|
||||||
};
|
|
||||||
|
|
||||||
// These need to check the int_dis field and if 0 then
|
// These need to check the int_dis field and if 0 then
|
||||||
// set appropriate bit in softint and checkinterrutps on the cpu
|
// set appropriate bit in softint and checkinterrutps on the cpu
|
||||||
|
@ -349,12 +169,6 @@ namespace SparcISA
|
||||||
typedef CpuEventWrapper<MiscRegFile,
|
typedef CpuEventWrapper<MiscRegFile,
|
||||||
&MiscRegFile::processHSTickCompare> HSTickCompareEvent;
|
&MiscRegFile::processHSTickCompare> HSTickCompareEvent;
|
||||||
HSTickCompareEvent *hSTickCompare;
|
HSTickCompareEvent *hSTickCompare;
|
||||||
|
|
||||||
/** Fullsystem only register version of ReadRegWithEffect() */
|
|
||||||
MiscReg readFSRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc);
|
|
||||||
/** Fullsystem only register version of SetRegWithEffect() */
|
|
||||||
Fault setFSRegWithEffect(int miscReg, const MiscReg &val,
|
|
||||||
ThreadContext * tc);
|
|
||||||
#endif
|
#endif
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -374,6 +188,16 @@ namespace SparcISA
|
||||||
void setRegWithEffect(int miscReg,
|
void setRegWithEffect(int miscReg,
|
||||||
const MiscReg &val, ThreadContext * tc);
|
const MiscReg &val, ThreadContext * tc);
|
||||||
|
|
||||||
|
ASI getInstAsid()
|
||||||
|
{
|
||||||
|
return implicitInstAsi;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASI getDataAsid()
|
||||||
|
{
|
||||||
|
return implicitDataAsi;
|
||||||
|
}
|
||||||
|
|
||||||
void serialize(std::ostream & os);
|
void serialize(std::ostream & os);
|
||||||
|
|
||||||
void unserialize(Checkpoint * cp, const std::string & section);
|
void unserialize(Checkpoint * cp, const std::string & section);
|
||||||
|
@ -382,9 +206,10 @@ namespace SparcISA
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
bool isHyperPriv() { return hpstateFields.hpriv; }
|
bool isHyperPriv() { return (hpstate & (1 << 2)); }
|
||||||
bool isPriv() { return hpstateFields.hpriv || pstateFields.priv; }
|
bool isPriv() { return (hpstate & (1 << 2)) || (pstate & (1 << 2)); }
|
||||||
bool isNonPriv() { return !isPriv(); }
|
bool isNonPriv() { return !isPriv(); }
|
||||||
|
inline void setImplicitAsis();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
* Ali Saidi
|
* Ali Saidi
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "arch/sparc/asi.hh"
|
||||||
#include "arch/sparc/isa_traits.hh"
|
#include "arch/sparc/isa_traits.hh"
|
||||||
#include "arch/sparc/process.hh"
|
#include "arch/sparc/process.hh"
|
||||||
#include "base/loader/object_file.hh"
|
#include "base/loader/object_file.hh"
|
||||||
|
@ -105,6 +106,8 @@ SparcLiveProcess::startup()
|
||||||
threadContexts[0]->setMiscReg(MISCREG_WSTATE, 0);
|
threadContexts[0]->setMiscReg(MISCREG_WSTATE, 0);
|
||||||
//Set the trap level to 0
|
//Set the trap level to 0
|
||||||
threadContexts[0]->setMiscReg(MISCREG_TL, 0);
|
threadContexts[0]->setMiscReg(MISCREG_TL, 0);
|
||||||
|
//Set the ASI register to something fixed
|
||||||
|
threadContexts[0]->setMiscReg(MISCREG_ASI, ASI_PRIMARY);
|
||||||
}
|
}
|
||||||
|
|
||||||
m5_auxv_t buildAuxVect(int64_t type, int64_t val)
|
m5_auxv_t buildAuxVect(int64_t type, int64_t val)
|
||||||
|
|
|
@ -79,24 +79,20 @@ MiscReg RegFile::readMiscReg(int miscReg)
|
||||||
return miscRegFile.readReg(miscReg);
|
return miscRegFile.readReg(miscReg);
|
||||||
}
|
}
|
||||||
|
|
||||||
MiscReg RegFile::readMiscRegWithEffect(int miscReg,
|
MiscReg RegFile::readMiscRegWithEffect(int miscReg, ThreadContext *tc)
|
||||||
Fault &fault, ThreadContext *tc)
|
|
||||||
{
|
{
|
||||||
fault = NoFault;
|
|
||||||
return miscRegFile.readRegWithEffect(miscReg, tc);
|
return miscRegFile.readRegWithEffect(miscReg, tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault RegFile::setMiscReg(int miscReg, const MiscReg &val)
|
void RegFile::setMiscReg(int miscReg, const MiscReg &val)
|
||||||
{
|
{
|
||||||
miscRegFile.setReg(miscReg, val);
|
miscRegFile.setReg(miscReg, val);
|
||||||
return NoFault;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault RegFile::setMiscRegWithEffect(int miscReg, const MiscReg &val,
|
void RegFile::setMiscRegWithEffect(int miscReg, const MiscReg &val,
|
||||||
ThreadContext * tc)
|
ThreadContext * tc)
|
||||||
{
|
{
|
||||||
miscRegFile.setRegWithEffect(miscReg, val, tc);
|
miscRegFile.setRegWithEffect(miscReg, val, tc);
|
||||||
return NoFault;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatReg RegFile::readFloatReg(int floatReg, int width)
|
FloatReg RegFile::readFloatReg(int floatReg, int width)
|
||||||
|
@ -122,27 +118,26 @@ FloatRegBits RegFile::readFloatRegBits(int floatReg)
|
||||||
FloatRegFile::SingleWidth);
|
FloatRegFile::SingleWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault RegFile::setFloatReg(int floatReg, const FloatReg &val, int width)
|
void RegFile::setFloatReg(int floatReg, const FloatReg &val, int width)
|
||||||
{
|
{
|
||||||
return floatRegFile.setReg(floatReg, val, width);
|
floatRegFile.setReg(floatReg, val, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault RegFile::setFloatReg(int floatReg, const FloatReg &val)
|
void RegFile::setFloatReg(int floatReg, const FloatReg &val)
|
||||||
{
|
{
|
||||||
//Use the "natural" width of a single float
|
//Use the "natural" width of a single float
|
||||||
return setFloatReg(floatReg, val, FloatRegFile::SingleWidth);
|
setFloatReg(floatReg, val, FloatRegFile::SingleWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault RegFile::setFloatRegBits(int floatReg, const FloatRegBits &val, int width)
|
void RegFile::setFloatRegBits(int floatReg, const FloatRegBits &val, int width)
|
||||||
{
|
{
|
||||||
return floatRegFile.setRegBits(floatReg, val, width);
|
floatRegFile.setRegBits(floatReg, val, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault RegFile::setFloatRegBits(int floatReg, const FloatRegBits &val)
|
void RegFile::setFloatRegBits(int floatReg, const FloatRegBits &val)
|
||||||
{
|
{
|
||||||
//Use the "natural" width of a single float
|
//Use the "natural" width of a single float
|
||||||
return floatRegFile.setRegBits(floatReg, val,
|
floatRegFile.setRegBits(floatReg, val, FloatRegFile::SingleWidth);
|
||||||
FloatRegFile::SingleWidth);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IntReg RegFile::readIntReg(int intReg)
|
IntReg RegFile::readIntReg(int intReg)
|
||||||
|
@ -150,9 +145,9 @@ IntReg RegFile::readIntReg(int intReg)
|
||||||
return intRegFile.readReg(intReg);
|
return intRegFile.readReg(intReg);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault RegFile::setIntReg(int intReg, const IntReg &val)
|
void RegFile::setIntReg(int intReg, const IntReg &val)
|
||||||
{
|
{
|
||||||
return intRegFile.setReg(intReg, val);
|
intRegFile.setReg(intReg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegFile::serialize(std::ostream &os)
|
void RegFile::serialize(std::ostream &os)
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
#ifndef __ARCH_SPARC_REGFILE_HH__
|
#ifndef __ARCH_SPARC_REGFILE_HH__
|
||||||
#define __ARCH_SPARC_REGFILE_HH__
|
#define __ARCH_SPARC_REGFILE_HH__
|
||||||
|
|
||||||
#include "arch/sparc/faults.hh"
|
|
||||||
#include "arch/sparc/floatregfile.hh"
|
#include "arch/sparc/floatregfile.hh"
|
||||||
#include "arch/sparc/intregfile.hh"
|
#include "arch/sparc/intregfile.hh"
|
||||||
#include "arch/sparc/isa_traits.hh"
|
#include "arch/sparc/isa_traits.hh"
|
||||||
|
@ -76,14 +75,23 @@ namespace SparcISA
|
||||||
|
|
||||||
MiscReg readMiscReg(int miscReg);
|
MiscReg readMiscReg(int miscReg);
|
||||||
|
|
||||||
MiscReg readMiscRegWithEffect(int miscReg,
|
MiscReg readMiscRegWithEffect(int miscReg, ThreadContext *tc);
|
||||||
Fault &fault, ThreadContext *tc);
|
|
||||||
|
|
||||||
Fault setMiscReg(int miscReg, const MiscReg &val);
|
void setMiscReg(int miscReg, const MiscReg &val);
|
||||||
|
|
||||||
Fault setMiscRegWithEffect(int miscReg, const MiscReg &val,
|
void setMiscRegWithEffect(int miscReg, const MiscReg &val,
|
||||||
ThreadContext * tc);
|
ThreadContext * tc);
|
||||||
|
|
||||||
|
ASI instAsid()
|
||||||
|
{
|
||||||
|
return miscRegFile.getInstAsid();
|
||||||
|
}
|
||||||
|
|
||||||
|
ASI dataAsid()
|
||||||
|
{
|
||||||
|
return miscRegFile.getDataAsid();
|
||||||
|
}
|
||||||
|
|
||||||
FloatReg readFloatReg(int floatReg, int width);
|
FloatReg readFloatReg(int floatReg, int width);
|
||||||
|
|
||||||
FloatReg readFloatReg(int floatReg);
|
FloatReg readFloatReg(int floatReg);
|
||||||
|
@ -92,17 +100,17 @@ namespace SparcISA
|
||||||
|
|
||||||
FloatRegBits readFloatRegBits(int floatReg);
|
FloatRegBits readFloatRegBits(int floatReg);
|
||||||
|
|
||||||
Fault setFloatReg(int floatReg, const FloatReg &val, int width);
|
void setFloatReg(int floatReg, const FloatReg &val, int width);
|
||||||
|
|
||||||
Fault setFloatReg(int floatReg, const FloatReg &val);
|
void setFloatReg(int floatReg, const FloatReg &val);
|
||||||
|
|
||||||
Fault setFloatRegBits(int floatReg, const FloatRegBits &val, int width);
|
void setFloatRegBits(int floatReg, const FloatRegBits &val, int width);
|
||||||
|
|
||||||
Fault setFloatRegBits(int floatReg, const FloatRegBits &val);
|
void setFloatRegBits(int floatReg, const FloatRegBits &val);
|
||||||
|
|
||||||
IntReg readIntReg(int intReg);
|
IntReg readIntReg(int intReg);
|
||||||
|
|
||||||
Fault setIntReg(int intReg, const IntReg &val);
|
void setIntReg(int intReg, const IntReg &val);
|
||||||
|
|
||||||
void serialize(std::ostream &os);
|
void serialize(std::ostream &os);
|
||||||
void unserialize(Checkpoint *cp, const std::string §ion);
|
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||||
|
|
203
src/arch/sparc/remote_gdb.cc
Normal file
203
src/arch/sparc/remote_gdb.cc
Normal file
|
@ -0,0 +1,203 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2002-2005 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Nathan Binkert
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1990, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* This software was developed by the Computer Systems Engineering group
|
||||||
|
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||||
|
* contributed to Berkeley.
|
||||||
|
*
|
||||||
|
* All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Lawrence Berkeley Laboratories.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Jason R. Thorpe.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the NetBSD
|
||||||
|
* Foundation, Inc. and its contributors.
|
||||||
|
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $NetBSD: kgdb_stub.c,v 1.8 2001/07/07 22:58:00 wdk Exp $
|
||||||
|
*
|
||||||
|
* Taken from NetBSD
|
||||||
|
*
|
||||||
|
* "Stub" to allow remote cpu to debug over a serial line using gdb.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/signal.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "arch/vtophys.hh"
|
||||||
|
#include "arch/sparc/remote_gdb.hh"
|
||||||
|
#include "base/intmath.hh"
|
||||||
|
#include "base/remote_gdb.hh"
|
||||||
|
#include "base/socket.hh"
|
||||||
|
#include "base/trace.hh"
|
||||||
|
#include "config/full_system.hh"
|
||||||
|
#include "cpu/thread_context.hh"
|
||||||
|
#include "cpu/static_inst.hh"
|
||||||
|
#include "mem/physical.hh"
|
||||||
|
#include "mem/port.hh"
|
||||||
|
#include "sim/system.hh"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace TheISA;
|
||||||
|
|
||||||
|
RemoteGDB::RemoteGDB(System *_system, ThreadContext *c)
|
||||||
|
: BaseRemoteGDB(_system, c, NumGDBRegs)
|
||||||
|
{}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
// RemoteGDB::acc
|
||||||
|
//
|
||||||
|
// Determine if the mapping at va..(va+len) is valid.
|
||||||
|
//
|
||||||
|
bool
|
||||||
|
RemoteGDB::acc(Addr va, size_t len)
|
||||||
|
{
|
||||||
|
//@Todo In NetBSD, this function checks if all addresses
|
||||||
|
//from va to va + len have valid page mape entries. Not
|
||||||
|
//sure how this will work for other OSes or in general.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
// RemoteGDB::getregs
|
||||||
|
//
|
||||||
|
// Translate the kernel debugger register format into
|
||||||
|
// the GDB register format.
|
||||||
|
void
|
||||||
|
RemoteGDB::getregs()
|
||||||
|
{
|
||||||
|
memset(gdbregs.regs, 0, gdbregs.size);
|
||||||
|
|
||||||
|
gdbregs.regs[RegPc] = context->readPC();
|
||||||
|
gdbregs.regs[RegNpc] = context->readNextPC();
|
||||||
|
for(int x = RegG0; x <= RegI0 + 7; x++)
|
||||||
|
gdbregs.regs[x] = context->readIntReg(x - RegG0);
|
||||||
|
//Floating point registers are left at 0 in netbsd
|
||||||
|
//All registers other than the pc, npc and int regs
|
||||||
|
//are ignored as well.
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
// RemoteGDB::setregs
|
||||||
|
//
|
||||||
|
// Translate the GDB register format into the kernel
|
||||||
|
// debugger register format.
|
||||||
|
//
|
||||||
|
void
|
||||||
|
RemoteGDB::setregs()
|
||||||
|
{
|
||||||
|
context->setPC(gdbregs.regs[RegPc]);
|
||||||
|
context->setNextPC(gdbregs.regs[RegNpc]);
|
||||||
|
for(int x = RegG0; x <= RegI0 + 7; x++)
|
||||||
|
context->setIntReg(x - RegG0, gdbregs.regs[x]);
|
||||||
|
//Only the integer registers, pc and npc are set in netbsd
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RemoteGDB::clearSingleStep()
|
||||||
|
{
|
||||||
|
panic("SPARC does not support hardware single stepping\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RemoteGDB::setSingleStep()
|
||||||
|
{
|
||||||
|
panic("SPARC does not support hardware single stepping\n");
|
||||||
|
}
|
78
src/arch/sparc/remote_gdb.hh
Normal file
78
src/arch/sparc/remote_gdb.hh
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2002-2005 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Nathan Binkert
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ARCH_ALPHA_REMOTE_GDB_HH__
|
||||||
|
#define __ARCH_ALPHA_REMOTE_GDB_HH__
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "arch/types.hh"
|
||||||
|
#include "base/remote_gdb.hh"
|
||||||
|
#include "cpu/pc_event.hh"
|
||||||
|
#include "base/pollevent.hh"
|
||||||
|
|
||||||
|
class System;
|
||||||
|
class ThreadContext;
|
||||||
|
class PhysicalMemory;
|
||||||
|
|
||||||
|
namespace SparcISA
|
||||||
|
{
|
||||||
|
class RemoteGDB : public BaseRemoteGDB
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
enum RegisterConstants
|
||||||
|
{
|
||||||
|
RegG0 = 0, RegO0 = 8, RegL0 = 16, RegI0 = 24,
|
||||||
|
RegF0 = 32, RegF32 = 64,
|
||||||
|
RegPc = 80, RegNpc, RegCcr, RegFsr, RegFprs, RegY, RegAsi,
|
||||||
|
RegVer, RegTick, RegPil, RegPstate,
|
||||||
|
RegTstate, RegTba, RegTl, RegTt, RegTpc, RegTnpc, RegWstate,
|
||||||
|
RegCwp, RegCansave, RegCanrestore, RegCleanwin, RegOtherwin,
|
||||||
|
RegAsr16 = 103,
|
||||||
|
RegIcc = 119, RegXcc,
|
||||||
|
RegFcc0 = 121,
|
||||||
|
NumGDBRegs
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
RemoteGDB(System *system, ThreadContext *context);
|
||||||
|
|
||||||
|
bool acc(Addr addr, size_t len);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void getregs();
|
||||||
|
void setregs();
|
||||||
|
|
||||||
|
void clearSingleStep();
|
||||||
|
void setSingleStep();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __ARCH_ALPHA_REMOTE_GDB_H__ */
|
372
src/arch/sparc/stacktrace.cc
Normal file
372
src/arch/sparc/stacktrace.cc
Normal file
|
@ -0,0 +1,372 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2005 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Nathan Binkert
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "arch/sparc/isa_traits.hh"
|
||||||
|
#include "arch/sparc/stacktrace.hh"
|
||||||
|
#include "arch/sparc/vtophys.hh"
|
||||||
|
#include "base/bitfield.hh"
|
||||||
|
#include "base/trace.hh"
|
||||||
|
#include "cpu/base.hh"
|
||||||
|
#include "cpu/thread_context.hh"
|
||||||
|
#include "sim/system.hh"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
namespace SparcISA
|
||||||
|
{
|
||||||
|
ProcessInfo::ProcessInfo(ThreadContext *_tc)
|
||||||
|
: tc(_tc)
|
||||||
|
{
|
||||||
|
Addr addr = 0;
|
||||||
|
|
||||||
|
VirtualPort *vp;
|
||||||
|
|
||||||
|
vp = tc->getVirtPort();
|
||||||
|
|
||||||
|
if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr))
|
||||||
|
panic("thread info not compiled into kernel\n");
|
||||||
|
thread_info_size = vp->readGtoH<int32_t>(addr);
|
||||||
|
|
||||||
|
if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr))
|
||||||
|
panic("thread info not compiled into kernel\n");
|
||||||
|
task_struct_size = vp->readGtoH<int32_t>(addr);
|
||||||
|
|
||||||
|
if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr))
|
||||||
|
panic("thread info not compiled into kernel\n");
|
||||||
|
task_off = vp->readGtoH<int32_t>(addr);
|
||||||
|
|
||||||
|
if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr))
|
||||||
|
panic("thread info not compiled into kernel\n");
|
||||||
|
pid_off = vp->readGtoH<int32_t>(addr);
|
||||||
|
|
||||||
|
if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr))
|
||||||
|
panic("thread info not compiled into kernel\n");
|
||||||
|
name_off = vp->readGtoH<int32_t>(addr);
|
||||||
|
|
||||||
|
tc->delVirtPort(vp);
|
||||||
|
}
|
||||||
|
|
||||||
|
Addr
|
||||||
|
ProcessInfo::task(Addr ksp) const
|
||||||
|
{
|
||||||
|
Addr base = ksp & ~0x3fff;
|
||||||
|
if (base == ULL(0xfffffc0000000000))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Addr tsk;
|
||||||
|
|
||||||
|
VirtualPort *vp;
|
||||||
|
|
||||||
|
vp = tc->getVirtPort();
|
||||||
|
tsk = vp->readGtoH<Addr>(base + task_off);
|
||||||
|
tc->delVirtPort(vp);
|
||||||
|
|
||||||
|
return tsk;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ProcessInfo::pid(Addr ksp) const
|
||||||
|
{
|
||||||
|
Addr task = this->task(ksp);
|
||||||
|
if (!task)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
uint16_t pd;
|
||||||
|
|
||||||
|
VirtualPort *vp;
|
||||||
|
|
||||||
|
vp = tc->getVirtPort();
|
||||||
|
pd = vp->readGtoH<uint16_t>(task + pid_off);
|
||||||
|
tc->delVirtPort(vp);
|
||||||
|
|
||||||
|
return pd;
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
ProcessInfo::name(Addr ksp) const
|
||||||
|
{
|
||||||
|
Addr task = this->task(ksp);
|
||||||
|
if (!task)
|
||||||
|
return "console";
|
||||||
|
|
||||||
|
char comm[256];
|
||||||
|
CopyStringOut(tc, comm, task + name_off, sizeof(comm));
|
||||||
|
if (!comm[0])
|
||||||
|
return "startup";
|
||||||
|
|
||||||
|
return comm;
|
||||||
|
}
|
||||||
|
|
||||||
|
StackTrace::StackTrace()
|
||||||
|
: tc(0), stack(64)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
StackTrace::StackTrace(ThreadContext *_tc, StaticInstPtr inst)
|
||||||
|
: tc(0), stack(64)
|
||||||
|
{
|
||||||
|
trace(_tc, inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
StackTrace::~StackTrace()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
StackTrace::trace(ThreadContext *_tc, bool is_call)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
tc = _tc;
|
||||||
|
|
||||||
|
bool usermode = (tc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0;
|
||||||
|
|
||||||
|
Addr pc = tc->readNextPC();
|
||||||
|
bool kernel = tc->getSystemPtr()->kernelStart <= pc &&
|
||||||
|
pc <= tc->getSystemPtr()->kernelEnd;
|
||||||
|
|
||||||
|
if (usermode) {
|
||||||
|
stack.push_back(user);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!kernel) {
|
||||||
|
stack.push_back(console);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
|
||||||
|
Addr ksp = tc->readIntReg(TheISA::StackPointerReg);
|
||||||
|
Addr bottom = ksp & ~0x3fff;
|
||||||
|
Addr addr;
|
||||||
|
|
||||||
|
if (is_call) {
|
||||||
|
if (!symtab->findNearestAddr(pc, addr))
|
||||||
|
panic("could not find address %#x", pc);
|
||||||
|
|
||||||
|
stack.push_back(addr);
|
||||||
|
pc = tc->readPC();
|
||||||
|
}
|
||||||
|
|
||||||
|
Addr ra;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
while (ksp > bottom) {
|
||||||
|
if (!symtab->findNearestAddr(pc, addr))
|
||||||
|
panic("could not find symbol for pc=%#x", pc);
|
||||||
|
assert(pc >= addr && "symbol botch: callpc < func");
|
||||||
|
|
||||||
|
stack.push_back(addr);
|
||||||
|
|
||||||
|
if (isEntry(addr))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (decodePrologue(ksp, pc, addr, size, ra)) {
|
||||||
|
if (!ra)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (size <= 0) {
|
||||||
|
stack.push_back(unknown);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pc = ra;
|
||||||
|
ksp += size;
|
||||||
|
} else {
|
||||||
|
stack.push_back(unknown);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool kernel = tc->getSystemPtr()->kernelStart <= pc &&
|
||||||
|
pc <= tc->getSystemPtr()->kernelEnd;
|
||||||
|
if (!kernel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (stack.size() >= 1000)
|
||||||
|
panic("unwinding too far");
|
||||||
|
}
|
||||||
|
|
||||||
|
panic("unwinding too far");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
StackTrace::isEntry(Addr addr)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp12))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp7))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp11))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp21))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp9))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp2))
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
StackTrace::decodeStack(MachInst inst, int &disp)
|
||||||
|
{
|
||||||
|
// lda $sp, -disp($sp)
|
||||||
|
//
|
||||||
|
// Opcode<31:26> == 0x08
|
||||||
|
// RA<25:21> == 30
|
||||||
|
// RB<20:16> == 30
|
||||||
|
// Disp<15:0>
|
||||||
|
const MachInst mem_mask = 0xffff0000;
|
||||||
|
const MachInst lda_pattern = 0x23de0000;
|
||||||
|
const MachInst lda_disp_mask = 0x0000ffff;
|
||||||
|
|
||||||
|
// subq $sp, disp, $sp
|
||||||
|
// addq $sp, disp, $sp
|
||||||
|
//
|
||||||
|
// Opcode<31:26> == 0x10
|
||||||
|
// RA<25:21> == 30
|
||||||
|
// Lit<20:13>
|
||||||
|
// One<12> = 1
|
||||||
|
// Func<11:5> == 0x20 (addq)
|
||||||
|
// Func<11:5> == 0x29 (subq)
|
||||||
|
// RC<4:0> == 30
|
||||||
|
const MachInst intop_mask = 0xffe01fff;
|
||||||
|
const MachInst addq_pattern = 0x43c0141e;
|
||||||
|
const MachInst subq_pattern = 0x43c0153e;
|
||||||
|
const MachInst intop_disp_mask = 0x001fe000;
|
||||||
|
const int intop_disp_shift = 13;
|
||||||
|
|
||||||
|
if ((inst & mem_mask) == lda_pattern)
|
||||||
|
disp = -sext<16>(inst & lda_disp_mask);
|
||||||
|
else if ((inst & intop_mask) == addq_pattern)
|
||||||
|
disp = -int((inst & intop_disp_mask) >> intop_disp_shift);
|
||||||
|
else if ((inst & intop_mask) == subq_pattern)
|
||||||
|
disp = int((inst & intop_disp_mask) >> intop_disp_shift);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
StackTrace::decodeSave(MachInst inst, int ®, int &disp)
|
||||||
|
{
|
||||||
|
// lda $stq, disp($sp)
|
||||||
|
//
|
||||||
|
// Opcode<31:26> == 0x08
|
||||||
|
// RA<25:21> == ?
|
||||||
|
// RB<20:16> == 30
|
||||||
|
// Disp<15:0>
|
||||||
|
const MachInst stq_mask = 0xfc1f0000;
|
||||||
|
const MachInst stq_pattern = 0xb41e0000;
|
||||||
|
const MachInst stq_disp_mask = 0x0000ffff;
|
||||||
|
const MachInst reg_mask = 0x03e00000;
|
||||||
|
const int reg_shift = 21;
|
||||||
|
|
||||||
|
if ((inst & stq_mask) == stq_pattern) {
|
||||||
|
reg = (inst & reg_mask) >> reg_shift;
|
||||||
|
disp = sext<16>(inst & stq_disp_mask);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decode the function prologue for the function we're in, and note
|
||||||
|
* which registers are stored where, and how large the stack frame is.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
|
||||||
|
int &size, Addr &ra)
|
||||||
|
{
|
||||||
|
size = 0;
|
||||||
|
ra = 0;
|
||||||
|
|
||||||
|
for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) {
|
||||||
|
MachInst inst;
|
||||||
|
CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst));
|
||||||
|
|
||||||
|
int reg, disp;
|
||||||
|
if (decodeStack(inst, disp)) {
|
||||||
|
if (size) {
|
||||||
|
// panic("decoding frame size again");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
size += disp;
|
||||||
|
} else if (decodeSave(inst, reg, disp)) {
|
||||||
|
if (!ra && reg == ReturnAddressReg) {
|
||||||
|
CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr));
|
||||||
|
if (!ra) {
|
||||||
|
// panic("no return address value pc=%#x\n", pc);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if TRACING_ON
|
||||||
|
void
|
||||||
|
StackTrace::dump()
|
||||||
|
{
|
||||||
|
StringWrap name(tc->getCpuPtr()->name());
|
||||||
|
SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
|
||||||
|
|
||||||
|
DPRINTFN("------ Stack ------\n");
|
||||||
|
|
||||||
|
string symbol;
|
||||||
|
for (int i = 0, size = stack.size(); i < size; ++i) {
|
||||||
|
Addr addr = stack[size - i - 1];
|
||||||
|
if (addr == user)
|
||||||
|
symbol = "user";
|
||||||
|
else if (addr == console)
|
||||||
|
symbol = "console";
|
||||||
|
else if (addr == unknown)
|
||||||
|
symbol = "unknown";
|
||||||
|
else
|
||||||
|
symtab->findSymbol(addr, symbol);
|
||||||
|
|
||||||
|
DPRINTFN("%#x: %s\n", addr, symbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -35,87 +35,90 @@
|
||||||
#include "cpu/static_inst.hh"
|
#include "cpu/static_inst.hh"
|
||||||
|
|
||||||
class ThreadContext;
|
class ThreadContext;
|
||||||
class StackTrace;
|
namespace SparcISA
|
||||||
|
|
||||||
class ProcessInfo
|
|
||||||
{
|
{
|
||||||
private:
|
class StackTrace;
|
||||||
ThreadContext *tc;
|
|
||||||
|
|
||||||
int thread_info_size;
|
class ProcessInfo
|
||||||
int task_struct_size;
|
|
||||||
int task_off;
|
|
||||||
int pid_off;
|
|
||||||
int name_off;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ProcessInfo(ThreadContext *_tc);
|
|
||||||
|
|
||||||
Addr task(Addr ksp) const;
|
|
||||||
int pid(Addr ksp) const;
|
|
||||||
std::string name(Addr ksp) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
class StackTrace
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
typedef TheISA::MachInst MachInst;
|
|
||||||
private:
|
|
||||||
ThreadContext *tc;
|
|
||||||
std::vector<Addr> stack;
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool isEntry(Addr addr);
|
|
||||||
bool decodePrologue(Addr sp, Addr callpc, Addr func, int &size, Addr &ra);
|
|
||||||
bool decodeSave(MachInst inst, int ®, int &disp);
|
|
||||||
bool decodeStack(MachInst inst, int &disp);
|
|
||||||
|
|
||||||
void trace(ThreadContext *tc, bool is_call);
|
|
||||||
|
|
||||||
public:
|
|
||||||
StackTrace();
|
|
||||||
StackTrace(ThreadContext *tc, StaticInstPtr inst);
|
|
||||||
~StackTrace();
|
|
||||||
|
|
||||||
void clear()
|
|
||||||
{
|
{
|
||||||
tc = 0;
|
private:
|
||||||
stack.clear();
|
ThreadContext *tc;
|
||||||
}
|
|
||||||
|
|
||||||
bool valid() const { return tc != NULL; }
|
int thread_info_size;
|
||||||
bool trace(ThreadContext *tc, StaticInstPtr inst);
|
int task_struct_size;
|
||||||
|
int task_off;
|
||||||
|
int pid_off;
|
||||||
|
int name_off;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const std::vector<Addr> &getstack() const { return stack; }
|
ProcessInfo(ThreadContext *_tc);
|
||||||
|
|
||||||
static const int user = 1;
|
Addr task(Addr ksp) const;
|
||||||
static const int console = 2;
|
int pid(Addr ksp) const;
|
||||||
static const int unknown = 3;
|
std::string name(Addr ksp) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class StackTrace
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
typedef TheISA::MachInst MachInst;
|
||||||
|
private:
|
||||||
|
ThreadContext *tc;
|
||||||
|
std::vector<Addr> stack;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isEntry(Addr addr);
|
||||||
|
bool decodePrologue(Addr sp, Addr callpc, Addr func, int &size, Addr &ra);
|
||||||
|
bool decodeSave(MachInst inst, int ®, int &disp);
|
||||||
|
bool decodeStack(MachInst inst, int &disp);
|
||||||
|
|
||||||
|
void trace(ThreadContext *tc, bool is_call);
|
||||||
|
|
||||||
|
public:
|
||||||
|
StackTrace();
|
||||||
|
StackTrace(ThreadContext *tc, StaticInstPtr inst);
|
||||||
|
~StackTrace();
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
tc = 0;
|
||||||
|
stack.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool valid() const { return tc != NULL; }
|
||||||
|
bool trace(ThreadContext *tc, StaticInstPtr inst);
|
||||||
|
|
||||||
|
public:
|
||||||
|
const std::vector<Addr> &getstack() const { return stack; }
|
||||||
|
|
||||||
|
static const int user = 1;
|
||||||
|
static const int console = 2;
|
||||||
|
static const int unknown = 3;
|
||||||
|
|
||||||
#if TRACING_ON
|
#if TRACING_ON
|
||||||
private:
|
private:
|
||||||
void dump();
|
void dump();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void dprintf() { if (DTRACE(Stack)) dump(); }
|
void dprintf() { if (DTRACE(Stack)) dump(); }
|
||||||
#else
|
#else
|
||||||
public:
|
public:
|
||||||
void dprintf() {}
|
void dprintf() {}
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
StackTrace::trace(ThreadContext *tc, StaticInstPtr inst)
|
StackTrace::trace(ThreadContext *tc, StaticInstPtr inst)
|
||||||
{
|
{
|
||||||
if (!inst->isCall() && !inst->isReturn())
|
if (!inst->isCall() && !inst->isReturn())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (valid())
|
if (valid())
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
trace(tc, !inst->isReturn());
|
trace(tc, !inst->isReturn());
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __ARCH_SPARC_STACKTRACE_HH__
|
#endif // __ARCH_SPARC_STACKTRACE_HH__
|
||||||
|
|
|
@ -42,42 +42,49 @@
|
||||||
using namespace BigEndianGuest;
|
using namespace BigEndianGuest;
|
||||||
|
|
||||||
SparcSystem::SparcSystem(Params *p)
|
SparcSystem::SparcSystem(Params *p)
|
||||||
: System(p), sysTick(0)
|
: System(p), sysTick(0),funcRomPort(p->name + "-fport")
|
||||||
|
|
||||||
{
|
{
|
||||||
resetSymtab = new SymbolTable;
|
resetSymtab = new SymbolTable;
|
||||||
hypervisorSymtab = new SymbolTable;
|
hypervisorSymtab = new SymbolTable;
|
||||||
openbootSymtab = new SymbolTable;
|
openbootSymtab = new SymbolTable;
|
||||||
|
|
||||||
|
Port *rom_port;
|
||||||
|
rom_port = params()->rom->getPort("functional");
|
||||||
|
funcRomPort.setPeer(rom_port);
|
||||||
|
rom_port->setPeer(&funcRomPort);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the boot code, and hypervisor into memory.
|
* Load the boot code, and hypervisor into memory.
|
||||||
*/
|
*/
|
||||||
// Read the reset binary
|
// Read the reset binary
|
||||||
reset = createObjectFile(params()->reset_bin);
|
reset = createObjectFile(params()->reset_bin, true);
|
||||||
if (reset == NULL)
|
if (reset == NULL)
|
||||||
fatal("Could not load reset binary %s", params()->reset_bin);
|
fatal("Could not load reset binary %s", params()->reset_bin);
|
||||||
|
|
||||||
// Read the openboot binary
|
// Read the openboot binary
|
||||||
openboot = createObjectFile(params()->openboot_bin);
|
openboot = createObjectFile(params()->openboot_bin, true);
|
||||||
if (openboot == NULL)
|
if (openboot == NULL)
|
||||||
fatal("Could not load openboot bianry %s", params()->openboot_bin);
|
fatal("Could not load openboot bianry %s", params()->openboot_bin);
|
||||||
|
|
||||||
// Read the hypervisor binary
|
// Read the hypervisor binary
|
||||||
hypervisor = createObjectFile(params()->hypervisor_bin);
|
hypervisor = createObjectFile(params()->hypervisor_bin, true);
|
||||||
if (hypervisor == NULL)
|
if (hypervisor == NULL)
|
||||||
fatal("Could not load hypervisor binary %s", params()->hypervisor_bin);
|
fatal("Could not load hypervisor binary %s", params()->hypervisor_bin);
|
||||||
|
|
||||||
|
|
||||||
// Load reset binary into memory
|
// Load reset binary into memory
|
||||||
reset->loadSections(&functionalPort, SparcISA::LoadAddrMask);
|
reset->setTextBase(params()->reset_addr);
|
||||||
|
reset->loadSections(&funcRomPort);
|
||||||
// Load the openboot binary
|
// Load the openboot binary
|
||||||
openboot->loadSections(&functionalPort, SparcISA::LoadAddrMask);
|
openboot->setTextBase(params()->openboot_addr);
|
||||||
|
openboot->loadSections(&funcRomPort);
|
||||||
// Load the hypervisor binary
|
// Load the hypervisor binary
|
||||||
hypervisor->loadSections(&functionalPort, SparcISA::LoadAddrMask);
|
hypervisor->setTextBase(params()->hypervisor_addr);
|
||||||
|
hypervisor->loadSections(&funcRomPort);
|
||||||
|
|
||||||
// load symbols
|
// load symbols
|
||||||
if (!reset->loadGlobalSymbols(reset))
|
if (!reset->loadGlobalSymbols(resetSymtab))
|
||||||
panic("could not load reset symbols\n");
|
panic("could not load reset symbols\n");
|
||||||
|
|
||||||
if (!openboot->loadGlobalSymbols(openbootSymtab))
|
if (!openboot->loadGlobalSymbols(openbootSymtab))
|
||||||
|
@ -141,13 +148,19 @@ SparcSystem::unserialize(Checkpoint *cp, const std::string §ion)
|
||||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcSystem)
|
BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcSystem)
|
||||||
|
|
||||||
SimObjectParam<PhysicalMemory *> physmem;
|
SimObjectParam<PhysicalMemory *> physmem;
|
||||||
|
SimObjectParam<PhysicalMemory *> rom;
|
||||||
SimpleEnumParam<System::MemoryMode> mem_mode;
|
SimpleEnumParam<System::MemoryMode> mem_mode;
|
||||||
|
|
||||||
|
Param<Addr> reset_addr;
|
||||||
|
Param<Addr> hypervisor_addr;
|
||||||
|
Param<Addr> openboot_addr;
|
||||||
|
|
||||||
Param<std::string> kernel;
|
Param<std::string> kernel;
|
||||||
Param<std::string> reset_bin;
|
Param<std::string> reset_bin;
|
||||||
Param<std::string> hypervisor_bin;
|
Param<std::string> hypervisor_bin;
|
||||||
Param<std::string> openboot_bin;
|
Param<std::string> openboot_bin;
|
||||||
|
|
||||||
|
Param<Tick> boot_cpu_frequency;
|
||||||
Param<std::string> boot_osflags;
|
Param<std::string> boot_osflags;
|
||||||
Param<std::string> readfile;
|
Param<std::string> readfile;
|
||||||
Param<unsigned int> init_param;
|
Param<unsigned int> init_param;
|
||||||
|
@ -156,20 +169,24 @@ END_DECLARE_SIM_OBJECT_PARAMS(SparcSystem)
|
||||||
|
|
||||||
BEGIN_INIT_SIM_OBJECT_PARAMS(SparcSystem)
|
BEGIN_INIT_SIM_OBJECT_PARAMS(SparcSystem)
|
||||||
|
|
||||||
INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
|
|
||||||
INIT_PARAM(physmem, "phsyical memory"),
|
INIT_PARAM(physmem, "phsyical memory"),
|
||||||
|
INIT_PARAM(rom, "ROM for boot code"),
|
||||||
INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
|
INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
|
||||||
System::MemoryModeStrings),
|
System::MemoryModeStrings),
|
||||||
|
|
||||||
|
INIT_PARAM(reset_addr, "Address that reset should be loaded at"),
|
||||||
|
INIT_PARAM(hypervisor_addr, "Address that hypervisor should be loaded at"),
|
||||||
|
INIT_PARAM(openboot_addr, "Address that openboot should be loaded at"),
|
||||||
|
|
||||||
INIT_PARAM(kernel, "file that contains the kernel code"),
|
INIT_PARAM(kernel, "file that contains the kernel code"),
|
||||||
INIT_PARAM(reset_bin, "file that contains the reset code"),
|
INIT_PARAM(reset_bin, "file that contains the reset code"),
|
||||||
INIT_PARAM(hypervisor_bin, "file that contains the hypervisor code"),
|
INIT_PARAM(hypervisor_bin, "file that contains the hypervisor code"),
|
||||||
INIT_PARAM(openboot_bin, "file that contains the openboot code"),
|
INIT_PARAM(openboot_bin, "file that contains the openboot code"),
|
||||||
|
INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
|
||||||
INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
|
INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
|
||||||
"a"),
|
"a"),
|
||||||
INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
|
INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
|
||||||
INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
|
INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0)
|
||||||
INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34),
|
|
||||||
INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10)
|
|
||||||
|
|
||||||
END_INIT_SIM_OBJECT_PARAMS(SparcSystem)
|
END_INIT_SIM_OBJECT_PARAMS(SparcSystem)
|
||||||
|
|
||||||
|
@ -179,16 +196,18 @@ CREATE_SIM_OBJECT(SparcSystem)
|
||||||
p->name = getInstanceName();
|
p->name = getInstanceName();
|
||||||
p->boot_cpu_frequency = boot_cpu_frequency;
|
p->boot_cpu_frequency = boot_cpu_frequency;
|
||||||
p->physmem = physmem;
|
p->physmem = physmem;
|
||||||
|
p->rom = rom;
|
||||||
p->mem_mode = mem_mode;
|
p->mem_mode = mem_mode;
|
||||||
p->kernel_path = kernel;
|
p->kernel_path = kernel;
|
||||||
|
p->reset_addr = reset_addr;
|
||||||
|
p->hypervisor_addr = hypervisor_addr;
|
||||||
|
p->openboot_addr = openboot_addr;
|
||||||
p->reset_bin = reset_bin;
|
p->reset_bin = reset_bin;
|
||||||
p->hypervisor_bin = hypervisor_bin;
|
p->hypervisor_bin = hypervisor_bin;
|
||||||
p->openboot_bin = openboot_bin;
|
p->openboot_bin = openboot_bin;
|
||||||
p->boot_osflags = boot_osflags;
|
p->boot_osflags = boot_osflags;
|
||||||
p->init_param = init_param;
|
p->init_param = init_param;
|
||||||
p->readfile = readfile;
|
p->readfile = readfile;
|
||||||
p->system_type = system_type;
|
|
||||||
p->system_rev = system_rev;
|
|
||||||
return new SparcSystem(p);
|
return new SparcSystem(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,12 +45,14 @@ class SparcSystem : public System
|
||||||
public:
|
public:
|
||||||
struct Params : public System::Params
|
struct Params : public System::Params
|
||||||
{
|
{
|
||||||
|
PhysicalMemory *rom;
|
||||||
|
Addr reset_addr;
|
||||||
|
Addr hypervisor_addr;
|
||||||
|
Addr openboot_addr;
|
||||||
std::string reset_bin;
|
std::string reset_bin;
|
||||||
std::string hypervison_bin;
|
std::string hypervisor_bin;
|
||||||
std::string openboot_bin;
|
std::string openboot_bin;
|
||||||
std::string boot_osflags;
|
std::string boot_osflags;
|
||||||
uint64_t system_type;
|
|
||||||
uint64_t system_rev;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SparcSystem(Params *p);
|
SparcSystem(Params *p);
|
||||||
|
@ -87,6 +89,9 @@ class SparcSystem : public System
|
||||||
/** System Tick for syncronized tick across all cpus. */
|
/** System Tick for syncronized tick across all cpus. */
|
||||||
Tick sysTick;
|
Tick sysTick;
|
||||||
|
|
||||||
|
/** functional port to ROM */
|
||||||
|
FunctionalPort funcRomPort;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const Params *params() const { return (const Params *)_params; }
|
const Params *params() const { return (const Params *)_params; }
|
||||||
|
|
||||||
|
@ -111,8 +116,11 @@ class SparcSystem : public System
|
||||||
return addFuncEvent<T>(openbootSymtab, lbl);
|
return addFuncEvent<T>(openbootSymtab, lbl);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Addr fixFuncEventAddr(Addr addr);
|
virtual Addr fixFuncEventAddr(Addr addr)
|
||||||
|
{
|
||||||
|
//XXX This may eventually have to do something useful.
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
79
src/arch/sparc/tlb.cc
Normal file
79
src/arch/sparc/tlb.cc
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2001-2005 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Nathan Binkert
|
||||||
|
* Steve Reinhardt
|
||||||
|
* Andrew Schultz
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "arch/sparc/tlb.hh"
|
||||||
|
#include "sim/builder.hh"
|
||||||
|
|
||||||
|
namespace SparcISA
|
||||||
|
{
|
||||||
|
DEFINE_SIM_OBJECT_CLASS_NAME("SparcTLB", TLB)
|
||||||
|
|
||||||
|
BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB)
|
||||||
|
|
||||||
|
Param<int> size;
|
||||||
|
|
||||||
|
END_DECLARE_SIM_OBJECT_PARAMS(ITB)
|
||||||
|
|
||||||
|
BEGIN_INIT_SIM_OBJECT_PARAMS(ITB)
|
||||||
|
|
||||||
|
INIT_PARAM_DFLT(size, "TLB size", 48)
|
||||||
|
|
||||||
|
END_INIT_SIM_OBJECT_PARAMS(ITB)
|
||||||
|
|
||||||
|
|
||||||
|
CREATE_SIM_OBJECT(ITB)
|
||||||
|
{
|
||||||
|
return new ITB(getInstanceName(), size);
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_SIM_OBJECT("SparcITB", ITB)
|
||||||
|
|
||||||
|
BEGIN_DECLARE_SIM_OBJECT_PARAMS(DTB)
|
||||||
|
|
||||||
|
Param<int> size;
|
||||||
|
|
||||||
|
END_DECLARE_SIM_OBJECT_PARAMS(DTB)
|
||||||
|
|
||||||
|
BEGIN_INIT_SIM_OBJECT_PARAMS(DTB)
|
||||||
|
|
||||||
|
INIT_PARAM_DFLT(size, "TLB size", 64)
|
||||||
|
|
||||||
|
END_INIT_SIM_OBJECT_PARAMS(DTB)
|
||||||
|
|
||||||
|
|
||||||
|
CREATE_SIM_OBJECT(DTB)
|
||||||
|
{
|
||||||
|
return new DTB(getInstanceName(), size);
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_SIM_OBJECT("SparcDTB", DTB)
|
||||||
|
}
|
|
@ -31,5 +31,47 @@
|
||||||
#ifndef __ARCH_SPARC_TLB_HH__
|
#ifndef __ARCH_SPARC_TLB_HH__
|
||||||
#define __ARCH_SPARC_TLB_HH__
|
#define __ARCH_SPARC_TLB_HH__
|
||||||
|
|
||||||
|
#include "mem/request.hh"
|
||||||
|
#include "sim/faults.hh"
|
||||||
|
#include "sim/sim_object.hh"
|
||||||
|
|
||||||
|
class ThreadContext;
|
||||||
|
|
||||||
|
namespace SparcISA
|
||||||
|
{
|
||||||
|
class TLB : public SimObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TLB(const std::string &name, int size) : SimObject(name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ITB : public TLB
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ITB(const std::string &name, int size) : TLB(name, size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Fault translate(RequestPtr &req, ThreadContext *tc) const
|
||||||
|
{
|
||||||
|
return NoFault;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class DTB : public TLB
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DTB(const std::string &name, int size) : TLB(name, size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Fault translate(RequestPtr &req, ThreadContext *tc, bool write) const
|
||||||
|
{
|
||||||
|
return NoFault;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif // __ARCH_SPARC_TLB_HH__
|
#endif // __ARCH_SPARC_TLB_HH__
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#ifndef __ARCH_SPARC_UTILITY_HH__
|
#ifndef __ARCH_SPARC_UTILITY_HH__
|
||||||
#define __ARCH_SPARC_UTILITY_HH__
|
#define __ARCH_SPARC_UTILITY_HH__
|
||||||
|
|
||||||
|
#include "arch/sparc/faults.hh"
|
||||||
#include "arch/sparc/isa_traits.hh"
|
#include "arch/sparc/isa_traits.hh"
|
||||||
#include "base/misc.hh"
|
#include "base/misc.hh"
|
||||||
#include "base/bitfield.hh"
|
#include "base/bitfield.hh"
|
||||||
|
@ -38,6 +39,14 @@
|
||||||
|
|
||||||
namespace SparcISA
|
namespace SparcISA
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
inUserMode(ThreadContext *tc)
|
||||||
|
{
|
||||||
|
return !(tc->readMiscReg(MISCREG_PSTATE & (1 << 2)) ||
|
||||||
|
tc->readMiscReg(MISCREG_HPSTATE & (1 << 2)));
|
||||||
|
}
|
||||||
|
|
||||||
inline ExtMachInst
|
inline ExtMachInst
|
||||||
makeExtMI(MachInst inst, ThreadContext * xc) {
|
makeExtMI(MachInst inst, ThreadContext * xc) {
|
||||||
ExtMachInst emi = (unsigned MachInst) inst;
|
ExtMachInst emi = (unsigned MachInst) inst;
|
||||||
|
@ -99,6 +108,12 @@ namespace SparcISA
|
||||||
template <class TC>
|
template <class TC>
|
||||||
void zeroRegisters(TC *tc);
|
void zeroRegisters(TC *tc);
|
||||||
|
|
||||||
|
inline void initCPU(ThreadContext *tc, int cpuId)
|
||||||
|
{
|
||||||
|
static Fault por = new PowerOnReset();
|
||||||
|
por->invoke(tc);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace SparcISA
|
} // namespace SparcISA
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -32,135 +32,47 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "arch/alpha/ev5.hh"
|
#include "arch/sparc/vtophys.hh"
|
||||||
#include "arch/alpha/vtophys.hh"
|
|
||||||
#include "base/chunk_generator.hh"
|
#include "base/chunk_generator.hh"
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
#include "cpu/thread_context.hh"
|
#include "cpu/thread_context.hh"
|
||||||
#include "mem/vport.hh"
|
#include "mem/vport.hh"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace AlphaISA;
|
|
||||||
|
|
||||||
AlphaISA::PageTableEntry
|
namespace SparcISA
|
||||||
AlphaISA::kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vaddr)
|
|
||||||
{
|
{
|
||||||
Addr level1_pte = ptbr + vaddr.level1();
|
PageTableEntry kernel_pte_lookup(FunctionalPort *mem,
|
||||||
AlphaISA::PageTableEntry level1 = mem->read<uint64_t>(level1_pte);
|
Addr ptbr, VAddr vaddr)
|
||||||
if (!level1.valid()) {
|
{
|
||||||
DPRINTF(VtoPhys, "level 1 PTE not valid, va = %#\n", vaddr);
|
PageTableEntry pte(4);
|
||||||
return 0;
|
return pte;
|
||||||
}
|
}
|
||||||
|
|
||||||
Addr level2_pte = level1.paddr() + vaddr.level2();
|
Addr vtophys(Addr vaddr)
|
||||||
AlphaISA::PageTableEntry level2 = mem->read<uint64_t>(level2_pte);
|
{
|
||||||
if (!level2.valid()) {
|
return vaddr;
|
||||||
DPRINTF(VtoPhys, "level 2 PTE not valid, va = %#x\n", vaddr);
|
}
|
||||||
return 0;
|
|
||||||
}
|
Addr vtophys(ThreadContext *tc, Addr addr)
|
||||||
|
{
|
||||||
Addr level3_pte = level2.paddr() + vaddr.level3();
|
return addr;
|
||||||
AlphaISA::PageTableEntry level3 = mem->read<uint64_t>(level3_pte);
|
}
|
||||||
if (!level3.valid()) {
|
|
||||||
DPRINTF(VtoPhys, "level 3 PTE not valid, va = %#x\n", vaddr);
|
|
||||||
return 0;
|
void CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen)
|
||||||
}
|
{
|
||||||
return level3;
|
}
|
||||||
}
|
|
||||||
|
void CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen)
|
||||||
Addr
|
{
|
||||||
AlphaISA::vtophys(Addr vaddr)
|
}
|
||||||
{
|
|
||||||
Addr paddr = 0;
|
void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen)
|
||||||
if (AlphaISA::IsUSeg(vaddr))
|
{
|
||||||
DPRINTF(VtoPhys, "vtophys: invalid vaddr %#x", vaddr);
|
}
|
||||||
else if (AlphaISA::IsK0Seg(vaddr))
|
|
||||||
paddr = AlphaISA::K0Seg2Phys(vaddr);
|
void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr)
|
||||||
else
|
|
||||||
panic("vtophys: ptbr is not set on virtual lookup");
|
|
||||||
|
|
||||||
DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr);
|
|
||||||
|
|
||||||
return paddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Addr
|
|
||||||
AlphaISA::vtophys(ThreadContext *tc, Addr addr)
|
|
||||||
{
|
|
||||||
AlphaISA::VAddr vaddr = addr;
|
|
||||||
Addr ptbr = tc->readMiscReg(AlphaISA::IPR_PALtemp20);
|
|
||||||
Addr paddr = 0;
|
|
||||||
//@todo Andrew couldn't remember why he commented some of this code
|
|
||||||
//so I put it back in. Perhaps something to do with gdb debugging?
|
|
||||||
if (AlphaISA::PcPAL(vaddr) && (vaddr < EV5::PalMax)) {
|
|
||||||
paddr = vaddr & ~ULL(1);
|
|
||||||
} else {
|
|
||||||
if (AlphaISA::IsK0Seg(vaddr)) {
|
|
||||||
paddr = AlphaISA::K0Seg2Phys(vaddr);
|
|
||||||
} else if (!ptbr) {
|
|
||||||
paddr = vaddr;
|
|
||||||
} else {
|
|
||||||
AlphaISA::PageTableEntry pte =
|
|
||||||
kernel_pte_lookup(tc->getPhysPort(), ptbr, vaddr);
|
|
||||||
if (pte.valid())
|
|
||||||
paddr = pte.paddr() | vaddr.offset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr);
|
|
||||||
|
|
||||||
return paddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
AlphaISA::CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen)
|
|
||||||
{
|
|
||||||
uint8_t *dst = (uint8_t *)dest;
|
|
||||||
VirtualPort *vp = tc->getVirtPort(tc);
|
|
||||||
|
|
||||||
vp->readBlob(src, dst, cplen);
|
|
||||||
|
|
||||||
tc->delVirtPort(vp);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
AlphaISA::CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen)
|
|
||||||
{
|
|
||||||
uint8_t *src = (uint8_t *)source;
|
|
||||||
VirtualPort *vp = tc->getVirtPort(tc);
|
|
||||||
|
|
||||||
vp->writeBlob(dest, src, cplen);
|
|
||||||
|
|
||||||
tc->delVirtPort(vp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
AlphaISA::CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen)
|
|
||||||
{
|
|
||||||
int len = 0;
|
|
||||||
VirtualPort *vp = tc->getVirtPort(tc);
|
|
||||||
|
|
||||||
do {
|
|
||||||
vp->readBlob(vaddr++, (uint8_t*)dst++, 1);
|
|
||||||
len++;
|
|
||||||
} while (len < maxlen && dst[len] != 0 );
|
|
||||||
|
|
||||||
tc->delVirtPort(vp);
|
|
||||||
dst[len] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
AlphaISA::CopyStringIn(ThreadContext *tc, char *src, Addr vaddr)
|
|
||||||
{
|
|
||||||
VirtualPort *vp = tc->getVirtPort(tc);
|
|
||||||
for (ChunkGenerator gen(vaddr, strlen(src), AlphaISA::PageBytes); !gen.done();
|
|
||||||
gen.next())
|
|
||||||
{
|
{
|
||||||
vp->writeBlob(gen.addr(), (uint8_t*)src, gen.size());
|
|
||||||
src += gen.size();
|
|
||||||
}
|
}
|
||||||
tc->delVirtPort(vp);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
#include "base/loader/ecoff_object.hh"
|
#include "base/loader/ecoff_object.hh"
|
||||||
#include "base/loader/aout_object.hh"
|
#include "base/loader/aout_object.hh"
|
||||||
#include "base/loader/elf_object.hh"
|
#include "base/loader/elf_object.hh"
|
||||||
|
#include "base/loader/raw_object.hh"
|
||||||
|
|
||||||
#include "mem/translating_port.hh"
|
#include "mem/translating_port.hh"
|
||||||
|
|
||||||
|
@ -107,7 +108,7 @@ ObjectFile::close()
|
||||||
|
|
||||||
|
|
||||||
ObjectFile *
|
ObjectFile *
|
||||||
createObjectFile(const string &fname)
|
createObjectFile(const string &fname, bool raw)
|
||||||
{
|
{
|
||||||
// open the file
|
// open the file
|
||||||
int fd = open(fname.c_str(), O_RDONLY);
|
int fd = open(fname.c_str(), O_RDONLY);
|
||||||
|
@ -141,6 +142,9 @@ createObjectFile(const string &fname)
|
||||||
return fileObj;
|
return fileObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (raw)
|
||||||
|
return RawObject::tryFile(fname, fd, len, fileData);
|
||||||
|
|
||||||
// don't know what it is
|
// don't know what it is
|
||||||
close(fd);
|
close(fd);
|
||||||
munmap(fileData, len);
|
munmap(fileData, len);
|
||||||
|
|
|
@ -114,9 +114,11 @@ class ObjectFile
|
||||||
size_t textSize() const { return text.size; }
|
size_t textSize() const { return text.size; }
|
||||||
size_t dataSize() const { return data.size; }
|
size_t dataSize() const { return data.size; }
|
||||||
size_t bssSize() const { return bss.size; }
|
size_t bssSize() const { return bss.size; }
|
||||||
|
|
||||||
|
void setTextBase(Addr a) { text.baseAddr = a; }
|
||||||
};
|
};
|
||||||
|
|
||||||
ObjectFile *createObjectFile(const std::string &fname);
|
ObjectFile *createObjectFile(const std::string &fname, bool raw = false);
|
||||||
|
|
||||||
|
|
||||||
#endif // __OBJECT_FILE_HH__
|
#endif // __OBJECT_FILE_HH__
|
||||||
|
|
72
src/base/loader/raw_object.cc
Normal file
72
src/base/loader/raw_object.cc
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Steve Reinhardt
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "base/loader/raw_object.hh"
|
||||||
|
#include "base/trace.hh"
|
||||||
|
|
||||||
|
ObjectFile *
|
||||||
|
RawObject::tryFile(const std::string &fname, int fd, size_t len, uint8_t *data)
|
||||||
|
{
|
||||||
|
return new RawObject(fname, fd, len, data, ObjectFile::UnknownArch,
|
||||||
|
ObjectFile::UnknownOpSys);
|
||||||
|
}
|
||||||
|
|
||||||
|
RawObject::RawObject(const std::string &_filename, int _fd, size_t _len,
|
||||||
|
uint8_t *_data, Arch _arch, OpSys _opSys)
|
||||||
|
: ObjectFile(_filename, _fd, _len, _data, _arch, _opSys)
|
||||||
|
{
|
||||||
|
text.baseAddr = 0;
|
||||||
|
text.size = len;
|
||||||
|
text.fileImage = fileData;
|
||||||
|
|
||||||
|
data.baseAddr = 0;
|
||||||
|
data.size = 0;
|
||||||
|
data.fileImage = NULL;
|
||||||
|
|
||||||
|
bss.baseAddr = 0;
|
||||||
|
bss.size = 0;
|
||||||
|
bss.fileImage = NULL;
|
||||||
|
|
||||||
|
DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n",
|
||||||
|
text.baseAddr, text.size, data.baseAddr, data.size,
|
||||||
|
bss.baseAddr, bss.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RawObject::loadGlobalSymbols(SymbolTable *symtab)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RawObject::loadLocalSymbols(SymbolTable *symtab)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
53
src/base/loader/raw_object.hh
Normal file
53
src/base/loader/raw_object.hh
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006 The Regents of The University of Michigan
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Ali Saidi
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __BASE_LOADER_RAW_OBJECT_HH__
|
||||||
|
#define __BASE_LOADER_RAW_OBJECT_HH__
|
||||||
|
|
||||||
|
#include "base/loader/object_file.hh"
|
||||||
|
|
||||||
|
class RawObject: public ObjectFile
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
RawObject(const std::string &_filename, int _fd, size_t _len,
|
||||||
|
uint8_t *_data, Arch _arch, OpSys _opSys);
|
||||||
|
public:
|
||||||
|
virtual ~RawObject() {}
|
||||||
|
|
||||||
|
virtual bool loadGlobalSymbols(SymbolTable *symtab);
|
||||||
|
virtual bool loadLocalSymbols(SymbolTable *symtab);
|
||||||
|
|
||||||
|
static ObjectFile *tryFile(const std::string &fname, int fd, size_t len,
|
||||||
|
uint8_t *data);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __BASE_LOADER_RAW_OBJECT_HH__
|
|
@ -30,6 +30,9 @@
|
||||||
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#if defined(__sun__)
|
||||||
|
#include <sys/file.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
|
@ -32,6 +32,10 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
#if defined(__sun__)
|
||||||
|
#include <ieeefp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "sim/param.hh"
|
#include "sim/param.hh"
|
||||||
#include "base/random.hh"
|
#include "base/random.hh"
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
|
@ -65,12 +69,27 @@ getLong()
|
||||||
return mrand48();
|
return mrand48();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
m5round(double r)
|
||||||
|
{
|
||||||
|
#if defined(__sun__)
|
||||||
|
double val;
|
||||||
|
fp_rnd oldrnd = fpsetround(FP_RN);
|
||||||
|
val = rint(r);
|
||||||
|
fpsetround(oldrnd);
|
||||||
|
return val;
|
||||||
|
#else
|
||||||
|
return round(r);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int64_t
|
int64_t
|
||||||
getUniform(int64_t min, int64_t max)
|
getUniform(int64_t min, int64_t max)
|
||||||
{
|
{
|
||||||
double r;
|
double r;
|
||||||
r = drand48() * (max-min) + min;
|
r = drand48() * (max-min) + min;
|
||||||
return (int64_t)round(r);
|
|
||||||
|
return (int64_t)m5round(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
|
@ -78,7 +97,8 @@ getUniformPos(uint64_t min, uint64_t max)
|
||||||
{
|
{
|
||||||
double r;
|
double r;
|
||||||
r = drand48() * (max-min) + min;
|
r = drand48() * (max-min) + min;
|
||||||
return (uint64_t)round(r);
|
|
||||||
|
return (uint64_t)m5round(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
|
|
||||||
long getLong();
|
long getLong();
|
||||||
double getDouble();
|
double getDouble();
|
||||||
|
double m5random(double r);
|
||||||
uint64_t getUniformPos(uint64_t min, uint64_t max);
|
uint64_t getUniformPos(uint64_t min, uint64_t max);
|
||||||
int64_t getUniform(int64_t min, int64_t max);
|
int64_t getUniform(int64_t min, int64_t max);
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,6 @@
|
||||||
|
|
||||||
#include "arch/vtophys.hh"
|
#include "arch/vtophys.hh"
|
||||||
#include "base/intmath.hh"
|
#include "base/intmath.hh"
|
||||||
#include "base/kgdb.h"
|
|
||||||
#include "base/remote_gdb.hh"
|
#include "base/remote_gdb.hh"
|
||||||
#include "base/socket.hh"
|
#include "base/socket.hh"
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
|
@ -138,18 +137,18 @@ using namespace std;
|
||||||
using namespace TheISA;
|
using namespace TheISA;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
vector<RemoteGDB *> debuggers;
|
vector<BaseRemoteGDB *> debuggers;
|
||||||
int current_debugger = -1;
|
|
||||||
|
|
||||||
void
|
void
|
||||||
debugger()
|
debugger()
|
||||||
{
|
{
|
||||||
|
static int current_debugger = -1;
|
||||||
if (current_debugger >= 0 && current_debugger < debuggers.size()) {
|
if (current_debugger >= 0 && current_debugger < debuggers.size()) {
|
||||||
RemoteGDB *gdb = debuggers[current_debugger];
|
BaseRemoteGDB *gdb = debuggers[current_debugger];
|
||||||
if (!gdb->isattached())
|
if (!gdb->isattached())
|
||||||
gdb->listener->accept();
|
gdb->listener->accept();
|
||||||
if (gdb->isattached())
|
if (gdb->isattached())
|
||||||
gdb->trap(ALPHA_KENTRY_IF);
|
gdb->trap(SIGILL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -169,7 +168,7 @@ GDBListener::Event::process(int revent)
|
||||||
listener->accept();
|
listener->accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
GDBListener::GDBListener(RemoteGDB *g, int p)
|
GDBListener::GDBListener(BaseRemoteGDB *g, int p)
|
||||||
: event(NULL), gdb(g), port(p)
|
: event(NULL), gdb(g), port(p)
|
||||||
{
|
{
|
||||||
assert(!gdb->listener);
|
assert(!gdb->listener);
|
||||||
|
@ -229,55 +228,46 @@ GDBListener::accept()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
BaseRemoteGDB::Event::Event(BaseRemoteGDB *g, int fd, int e)
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
int digit2i(char);
|
|
||||||
char i2digit(int);
|
|
||||||
void mem2hex(void *, const void *, int);
|
|
||||||
const char *hex2mem(void *, const char *, int);
|
|
||||||
Addr hex2i(const char **);
|
|
||||||
|
|
||||||
RemoteGDB::Event::Event(RemoteGDB *g, int fd, int e)
|
|
||||||
: PollEvent(fd, e), gdb(g)
|
: PollEvent(fd, e), gdb(g)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void
|
void
|
||||||
RemoteGDB::Event::process(int revent)
|
BaseRemoteGDB::Event::process(int revent)
|
||||||
{
|
{
|
||||||
if (revent & POLLIN)
|
if (revent & POLLIN)
|
||||||
gdb->trap(ALPHA_KENTRY_IF);
|
gdb->trap(SIGILL);
|
||||||
else if (revent & POLLNVAL)
|
else if (revent & POLLNVAL)
|
||||||
gdb->detach();
|
gdb->detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoteGDB::RemoteGDB(System *_system, ThreadContext *c)
|
BaseRemoteGDB::BaseRemoteGDB(System *_system, ThreadContext *c, size_t cacheSize)
|
||||||
: event(NULL), listener(NULL), number(-1), fd(-1),
|
: event(NULL), listener(NULL), number(-1), fd(-1),
|
||||||
active(false), attached(false),
|
active(false), attached(false),
|
||||||
system(_system), pmem(_system->physmem), context(c)
|
system(_system), pmem(_system->physmem), context(c),
|
||||||
|
gdbregs(cacheSize)
|
||||||
{
|
{
|
||||||
memset(gdbregs, 0, sizeof(gdbregs));
|
memset(gdbregs.regs, 0, gdbregs.bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoteGDB::~RemoteGDB()
|
BaseRemoteGDB::~BaseRemoteGDB()
|
||||||
{
|
{
|
||||||
if (event)
|
if (event)
|
||||||
delete event;
|
delete event;
|
||||||
}
|
}
|
||||||
|
|
||||||
string
|
string
|
||||||
RemoteGDB::name()
|
BaseRemoteGDB::name()
|
||||||
{
|
{
|
||||||
return system->name() + ".remote_gdb";
|
return system->name() + ".remote_gdb";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
RemoteGDB::isattached()
|
BaseRemoteGDB::isattached()
|
||||||
{ return attached; }
|
{ return attached; }
|
||||||
|
|
||||||
void
|
void
|
||||||
RemoteGDB::attach(int f)
|
BaseRemoteGDB::attach(int f)
|
||||||
{
|
{
|
||||||
fd = f;
|
fd = f;
|
||||||
|
|
||||||
|
@ -289,7 +279,7 @@ RemoteGDB::attach(int f)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RemoteGDB::detach()
|
BaseRemoteGDB::detach()
|
||||||
{
|
{
|
||||||
attached = false;
|
attached = false;
|
||||||
close(fd);
|
close(fd);
|
||||||
|
@ -300,250 +290,50 @@ RemoteGDB::detach()
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
gdb_command(char cmd)
|
BaseRemoteGDB::gdb_command(char cmd)
|
||||||
{
|
{
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case KGDB_SIGNAL: return "KGDB_SIGNAL";
|
case GDBSignal: return "KGDB_SIGNAL";
|
||||||
case KGDB_SET_BAUD: return "KGDB_SET_BAUD";
|
case GDBSetBaud: return "KGDB_SET_BAUD";
|
||||||
case KGDB_SET_BREAK: return "KGDB_SET_BREAK";
|
case GDBSetBreak: return "KGDB_SET_BREAK";
|
||||||
case KGDB_CONT: return "KGDB_CONT";
|
case GDBCont: return "KGDB_CONT";
|
||||||
case KGDB_ASYNC_CONT: return "KGDB_ASYNC_CONT";
|
case GDBAsyncCont: return "KGDB_ASYNC_CONT";
|
||||||
case KGDB_DEBUG: return "KGDB_DEBUG";
|
case GDBDebug: return "KGDB_DEBUG";
|
||||||
case KGDB_DETACH: return "KGDB_DETACH";
|
case GDBDetach: return "KGDB_DETACH";
|
||||||
case KGDB_REG_R: return "KGDB_REG_R";
|
case GDBRegR: return "KGDB_REG_R";
|
||||||
case KGDB_REG_W: return "KGDB_REG_W";
|
case GDBRegW: return "KGDB_REG_W";
|
||||||
case KGDB_SET_THREAD: return "KGDB_SET_THREAD";
|
case GDBSetThread: return "KGDB_SET_THREAD";
|
||||||
case KGDB_CYCLE_STEP: return "KGDB_CYCLE_STEP";
|
case GDBCycleStep: return "KGDB_CYCLE_STEP";
|
||||||
case KGDB_SIG_CYCLE_STEP: return "KGDB_SIG_CYCLE_STEP";
|
case GDBSigCycleStep: return "KGDB_SIG_CYCLE_STEP";
|
||||||
case KGDB_KILL: return "KGDB_KILL";
|
case GDBKill: return "KGDB_KILL";
|
||||||
case KGDB_MEM_W: return "KGDB_MEM_W";
|
case GDBMemW: return "KGDB_MEM_W";
|
||||||
case KGDB_MEM_R: return "KGDB_MEM_R";
|
case GDBMemR: return "KGDB_MEM_R";
|
||||||
case KGDB_SET_REG: return "KGDB_SET_REG";
|
case GDBSetReg: return "KGDB_SET_REG";
|
||||||
case KGDB_READ_REG: return "KGDB_READ_REG";
|
case GDBReadReg: return "KGDB_READ_REG";
|
||||||
case KGDB_QUERY_VAR: return "KGDB_QUERY_VAR";
|
case GDBQueryVar: return "KGDB_QUERY_VAR";
|
||||||
case KGDB_SET_VAR: return "KGDB_SET_VAR";
|
case GDBSetVar: return "KGDB_SET_VAR";
|
||||||
case KGDB_RESET: return "KGDB_RESET";
|
case GDBReset: return "KGDB_RESET";
|
||||||
case KGDB_STEP: return "KGDB_STEP";
|
case GDBStep: return "KGDB_STEP";
|
||||||
case KGDB_ASYNC_STEP: return "KGDB_ASYNC_STEP";
|
case GDBAsyncStep: return "KGDB_ASYNC_STEP";
|
||||||
case KGDB_THREAD_ALIVE: return "KGDB_THREAD_ALIVE";
|
case GDBThreadAlive: return "KGDB_THREAD_ALIVE";
|
||||||
case KGDB_TARGET_EXIT: return "KGDB_TARGET_EXIT";
|
case GDBTargetExit: return "KGDB_TARGET_EXIT";
|
||||||
case KGDB_BINARY_DLOAD: return "KGDB_BINARY_DLOAD";
|
case GDBBinaryDload: return "KGDB_BINARY_DLOAD";
|
||||||
case KGDB_CLR_HW_BKPT: return "KGDB_CLR_HW_BKPT";
|
case GDBClrHwBkpt: return "KGDB_CLR_HW_BKPT";
|
||||||
case KGDB_SET_HW_BKPT: return "KGDB_SET_HW_BKPT";
|
case GDBSetHwBkpt: return "KGDB_SET_HW_BKPT";
|
||||||
case KGDB_START: return "KGDB_START";
|
case GDBStart: return "KGDB_START";
|
||||||
case KGDB_END: return "KGDB_END";
|
case GDBEnd: return "KGDB_END";
|
||||||
case KGDB_GOODP: return "KGDB_GOODP";
|
case GDBGoodP: return "KGDB_GOODP";
|
||||||
case KGDB_BADP: return "KGDB_BADP";
|
case GDBBadP: return "KGDB_BADP";
|
||||||
default: return "KGDB_UNKNOWN";
|
default: return "KGDB_UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
|
||||||
// RemoteGDB::acc
|
|
||||||
//
|
|
||||||
// Determine if the mapping at va..(va+len) is valid.
|
|
||||||
//
|
|
||||||
bool
|
|
||||||
RemoteGDB::acc(Addr va, size_t len)
|
|
||||||
{
|
|
||||||
Addr last_va;
|
|
||||||
|
|
||||||
va = TheISA::TruncPage(va);
|
|
||||||
last_va = TheISA::RoundPage(va + len);
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (TheISA::IsK0Seg(va)) {
|
|
||||||
if (va < (TheISA::K0SegBase + pmem->size())) {
|
|
||||||
DPRINTF(GDBAcc, "acc: Mapping is valid K0SEG <= "
|
|
||||||
"%#x < K0SEG + size\n", va);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
DPRINTF(GDBAcc, "acc: Mapping invalid %#x > K0SEG + size\n",
|
|
||||||
va);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This code says that all accesses to palcode (instruction and data)
|
|
||||||
* are valid since there isn't a va->pa mapping because palcode is
|
|
||||||
* accessed physically. At some point this should probably be cleaned up
|
|
||||||
* but there is no easy way to do it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (AlphaISA::PcPAL(va) || va < 0x10000)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
Addr ptbr = context->readMiscReg(AlphaISA::IPR_PALtemp20);
|
|
||||||
TheISA::PageTableEntry pte = TheISA::kernel_pte_lookup(context->getPhysPort(), ptbr, va);
|
|
||||||
if (!pte.valid()) {
|
|
||||||
DPRINTF(GDBAcc, "acc: %#x pte is invalid\n", va);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
va += TheISA::PageBytes;
|
|
||||||
} while (va < last_va);
|
|
||||||
|
|
||||||
DPRINTF(GDBAcc, "acc: %#x mapping is valid\n", va);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
|
||||||
// RemoteGDB::signal
|
|
||||||
//
|
|
||||||
// Translate a trap number into a Unix-compatible signal number.
|
|
||||||
// (GDB only understands Unix signal numbers.)
|
|
||||||
//
|
|
||||||
int
|
|
||||||
RemoteGDB::signal(int type)
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
case ALPHA_KENTRY_INT:
|
|
||||||
return (SIGTRAP);
|
|
||||||
|
|
||||||
case ALPHA_KENTRY_UNA:
|
|
||||||
return (SIGBUS);
|
|
||||||
|
|
||||||
case ALPHA_KENTRY_ARITH:
|
|
||||||
return (SIGFPE);
|
|
||||||
|
|
||||||
case ALPHA_KENTRY_IF:
|
|
||||||
return (SIGILL);
|
|
||||||
|
|
||||||
case ALPHA_KENTRY_MM:
|
|
||||||
return (SIGSEGV);
|
|
||||||
|
|
||||||
default:
|
|
||||||
panic("unknown signal type");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
|
||||||
// RemoteGDB::getregs
|
|
||||||
//
|
|
||||||
// Translate the kernel debugger register format into
|
|
||||||
// the GDB register format.
|
|
||||||
void
|
|
||||||
RemoteGDB::getregs()
|
|
||||||
{
|
|
||||||
memset(gdbregs, 0, sizeof(gdbregs));
|
|
||||||
|
|
||||||
gdbregs[KGDB_REG_PC] = context->readPC();
|
|
||||||
|
|
||||||
// @todo: Currently this is very Alpha specific.
|
|
||||||
if (AlphaISA::PcPAL(gdbregs[KGDB_REG_PC])) {
|
|
||||||
for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
|
|
||||||
gdbregs[i] = context->readIntReg(AlphaISA::reg_redir[i]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
|
|
||||||
gdbregs[i] = context->readIntReg(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef KGDB_FP_REGS
|
|
||||||
for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) {
|
|
||||||
gdbregs[i + KGDB_REG_F0] = context->readFloatRegBits(i);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
|
||||||
// RemoteGDB::setregs
|
|
||||||
//
|
|
||||||
// Translate the GDB register format into the kernel
|
|
||||||
// debugger register format.
|
|
||||||
//
|
|
||||||
void
|
|
||||||
RemoteGDB::setregs()
|
|
||||||
{
|
|
||||||
// @todo: Currently this is very Alpha specific.
|
|
||||||
if (AlphaISA::PcPAL(gdbregs[KGDB_REG_PC])) {
|
|
||||||
for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
|
|
||||||
context->setIntReg(AlphaISA::reg_redir[i], gdbregs[i]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
|
|
||||||
context->setIntReg(i, gdbregs[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef KGDB_FP_REGS
|
|
||||||
for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) {
|
|
||||||
context->setFloatRegBits(i, gdbregs[i + KGDB_REG_F0]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
context->setPC(gdbregs[KGDB_REG_PC]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RemoteGDB::setTempBreakpoint(TempBreakpoint &bkpt, Addr addr)
|
|
||||||
{
|
|
||||||
DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", addr);
|
|
||||||
|
|
||||||
bkpt.address = addr;
|
|
||||||
insertHardBreak(addr, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RemoteGDB::clearTempBreakpoint(TempBreakpoint &bkpt)
|
|
||||||
{
|
|
||||||
DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n",
|
|
||||||
bkpt.address);
|
|
||||||
|
|
||||||
|
|
||||||
removeHardBreak(bkpt.address, 4);
|
|
||||||
bkpt.address = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RemoteGDB::clearSingleStep()
|
|
||||||
{
|
|
||||||
DPRINTF(GDBMisc, "clearSingleStep bt_addr=%#x nt_addr=%#x\n",
|
|
||||||
takenBkpt.address, notTakenBkpt.address);
|
|
||||||
|
|
||||||
if (takenBkpt.address != 0)
|
|
||||||
clearTempBreakpoint(takenBkpt);
|
|
||||||
|
|
||||||
if (notTakenBkpt.address != 0)
|
|
||||||
clearTempBreakpoint(notTakenBkpt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RemoteGDB::setSingleStep()
|
|
||||||
{
|
|
||||||
Addr pc = context->readPC();
|
|
||||||
Addr npc, bpc;
|
|
||||||
bool set_bt = false;
|
|
||||||
|
|
||||||
npc = pc + sizeof(MachInst);
|
|
||||||
|
|
||||||
// User was stopped at pc, e.g. the instruction at pc was not
|
|
||||||
// executed.
|
|
||||||
MachInst inst = read<MachInst>(pc);
|
|
||||||
StaticInstPtr si(inst);
|
|
||||||
if (si->hasBranchTarget(pc, context, bpc)) {
|
|
||||||
// Don't bother setting a breakpoint on the taken branch if it
|
|
||||||
// is the same as the next pc
|
|
||||||
if (bpc != npc)
|
|
||||||
set_bt = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINTF(GDBMisc, "setSingleStep bt_addr=%#x nt_addr=%#x\n",
|
|
||||||
takenBkpt.address, notTakenBkpt.address);
|
|
||||||
|
|
||||||
setTempBreakpoint(notTakenBkpt, npc);
|
|
||||||
|
|
||||||
if (set_bt)
|
|
||||||
setTempBreakpoint(takenBkpt, bpc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////
|
/////////////////////////
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
RemoteGDB::getbyte()
|
BaseRemoteGDB::getbyte()
|
||||||
{
|
{
|
||||||
uint8_t b;
|
uint8_t b;
|
||||||
::read(fd, &b, 1);
|
::read(fd, &b, 1);
|
||||||
|
@ -551,14 +341,14 @@ RemoteGDB::getbyte()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RemoteGDB::putbyte(uint8_t b)
|
BaseRemoteGDB::putbyte(uint8_t b)
|
||||||
{
|
{
|
||||||
::write(fd, &b, 1);
|
::write(fd, &b, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send a packet to gdb
|
// Send a packet to gdb
|
||||||
void
|
void
|
||||||
RemoteGDB::send(const char *bp)
|
BaseRemoteGDB::send(const char *bp)
|
||||||
{
|
{
|
||||||
const char *p;
|
const char *p;
|
||||||
uint8_t csum, c;
|
uint8_t csum, c;
|
||||||
|
@ -567,20 +357,26 @@ RemoteGDB::send(const char *bp)
|
||||||
|
|
||||||
do {
|
do {
|
||||||
p = bp;
|
p = bp;
|
||||||
putbyte(KGDB_START);
|
//Start sending a packet
|
||||||
|
putbyte(GDBStart);
|
||||||
|
//Send the contents, and also keep a check sum.
|
||||||
for (csum = 0; (c = *p); p++) {
|
for (csum = 0; (c = *p); p++) {
|
||||||
putbyte(c);
|
putbyte(c);
|
||||||
csum += c;
|
csum += c;
|
||||||
}
|
}
|
||||||
putbyte(KGDB_END);
|
//Send the ending character.
|
||||||
|
putbyte(GDBEnd);
|
||||||
|
//Sent the checksum.
|
||||||
putbyte(i2digit(csum >> 4));
|
putbyte(i2digit(csum >> 4));
|
||||||
putbyte(i2digit(csum));
|
putbyte(i2digit(csum));
|
||||||
} while ((c = getbyte() & 0x7f) == KGDB_BADP);
|
//Try transmitting over and over again until the other end doesn't send an
|
||||||
|
//error back.
|
||||||
|
} while ((c = getbyte() & 0x7f) == GDBBadP);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Receive a packet from gdb
|
// Receive a packet from gdb
|
||||||
int
|
int
|
||||||
RemoteGDB::recv(char *bp, int maxlen)
|
BaseRemoteGDB::recv(char *bp, int maxlen)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
int c, csum;
|
int c, csum;
|
||||||
|
@ -589,28 +385,37 @@ RemoteGDB::recv(char *bp, int maxlen)
|
||||||
do {
|
do {
|
||||||
p = bp;
|
p = bp;
|
||||||
csum = len = 0;
|
csum = len = 0;
|
||||||
while ((c = getbyte()) != KGDB_START)
|
//Find the beginning of a packet
|
||||||
|
while ((c = getbyte()) != GDBStart)
|
||||||
;
|
;
|
||||||
|
|
||||||
while ((c = getbyte()) != KGDB_END && len < maxlen) {
|
//Read until you find the end of the data in the packet, and keep
|
||||||
|
//track of the check sum.
|
||||||
|
while ((c = getbyte()) != GDBEnd && len < maxlen) {
|
||||||
c &= 0x7f;
|
c &= 0x7f;
|
||||||
csum += c;
|
csum += c;
|
||||||
*p++ = c;
|
*p++ = c;
|
||||||
len++;
|
len++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Mask the check sum, and terminate the command string.
|
||||||
csum &= 0xff;
|
csum &= 0xff;
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
|
|
||||||
|
//If the command was too long, report an error.
|
||||||
if (len >= maxlen) {
|
if (len >= maxlen) {
|
||||||
putbyte(KGDB_BADP);
|
putbyte(GDBBadP);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Bring in the checksum. If the check sum matches, csum will be 0.
|
||||||
csum -= digit2i(getbyte()) * 16;
|
csum -= digit2i(getbyte()) * 16;
|
||||||
csum -= digit2i(getbyte());
|
csum -= digit2i(getbyte());
|
||||||
|
|
||||||
|
//If the check sum was correct
|
||||||
if (csum == 0) {
|
if (csum == 0) {
|
||||||
putbyte(KGDB_GOODP);
|
//Report that the packet was received correctly
|
||||||
|
putbyte(GDBGoodP);
|
||||||
// Sequence present?
|
// Sequence present?
|
||||||
if (bp[2] == ':') {
|
if (bp[2] == ':') {
|
||||||
putbyte(bp[0]);
|
putbyte(bp[0]);
|
||||||
|
@ -620,7 +425,8 @@ RemoteGDB::recv(char *bp, int maxlen)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
putbyte(KGDB_BADP);
|
//Otherwise, report that there was a mistake.
|
||||||
|
putbyte(GDBBadP);
|
||||||
} while (1);
|
} while (1);
|
||||||
|
|
||||||
DPRINTF(GDBRecv, "recv: %s: %s\n", gdb_command(*bp), bp);
|
DPRINTF(GDBRecv, "recv: %s: %s\n", gdb_command(*bp), bp);
|
||||||
|
@ -630,7 +436,7 @@ RemoteGDB::recv(char *bp, int maxlen)
|
||||||
|
|
||||||
// Read bytes from kernel address space for debugger.
|
// Read bytes from kernel address space for debugger.
|
||||||
bool
|
bool
|
||||||
RemoteGDB::read(Addr vaddr, size_t size, char *data)
|
BaseRemoteGDB::read(Addr vaddr, size_t size, char *data)
|
||||||
{
|
{
|
||||||
static Addr lastaddr = 0;
|
static Addr lastaddr = 0;
|
||||||
static size_t lastsize = 0;
|
static size_t lastsize = 0;
|
||||||
|
@ -662,7 +468,7 @@ RemoteGDB::read(Addr vaddr, size_t size, char *data)
|
||||||
|
|
||||||
// Write bytes to kernel address space for debugger.
|
// Write bytes to kernel address space for debugger.
|
||||||
bool
|
bool
|
||||||
RemoteGDB::write(Addr vaddr, size_t size, const char *data)
|
BaseRemoteGDB::write(Addr vaddr, size_t size, const char *data)
|
||||||
{
|
{
|
||||||
static Addr lastaddr = 0;
|
static Addr lastaddr = 0;
|
||||||
static size_t lastsize = 0;
|
static size_t lastsize = 0;
|
||||||
|
@ -685,21 +491,15 @@ RemoteGDB::write(Addr vaddr, size_t size, const char *data)
|
||||||
vp->writeBlob(vaddr, (uint8_t*)data, size);
|
vp->writeBlob(vaddr, (uint8_t*)data, size);
|
||||||
context->delVirtPort(vp);
|
context->delVirtPort(vp);
|
||||||
|
|
||||||
#ifdef IMB
|
|
||||||
alpha_pal_imb();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PCEventQueue *BaseRemoteGDB::getPcEventQueue()
|
||||||
PCEventQueue *RemoteGDB::getPcEventQueue()
|
|
||||||
{
|
{
|
||||||
return &system->pcEventQueue;
|
return &system->pcEventQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BaseRemoteGDB::HardBreakpoint::HardBreakpoint(BaseRemoteGDB *_gdb, Addr pc)
|
||||||
RemoteGDB::HardBreakpoint::HardBreakpoint(RemoteGDB *_gdb, Addr pc)
|
|
||||||
: PCEvent(_gdb->getPcEventQueue(), "HardBreakpoint Event", pc),
|
: PCEvent(_gdb->getPcEventQueue(), "HardBreakpoint Event", pc),
|
||||||
gdb(_gdb), refcount(0)
|
gdb(_gdb), refcount(0)
|
||||||
{
|
{
|
||||||
|
@ -707,25 +507,25 @@ RemoteGDB::HardBreakpoint::HardBreakpoint(RemoteGDB *_gdb, Addr pc)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RemoteGDB::HardBreakpoint::process(ThreadContext *tc)
|
BaseRemoteGDB::HardBreakpoint::process(ThreadContext *tc)
|
||||||
{
|
{
|
||||||
DPRINTF(GDBMisc, "handling hardware breakpoint at %#x\n", pc());
|
DPRINTF(GDBMisc, "handling hardware breakpoint at %#x\n", pc());
|
||||||
|
|
||||||
if (tc == gdb->context)
|
if (tc == gdb->context)
|
||||||
gdb->trap(ALPHA_KENTRY_INT);
|
gdb->trap(SIGTRAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
RemoteGDB::insertSoftBreak(Addr addr, size_t len)
|
BaseRemoteGDB::insertSoftBreak(Addr addr, size_t len)
|
||||||
{
|
{
|
||||||
if (len != sizeof(MachInst))
|
if (len != sizeof(TheISA::MachInst))
|
||||||
panic("invalid length\n");
|
panic("invalid length\n");
|
||||||
|
|
||||||
return insertHardBreak(addr, len);
|
return insertHardBreak(addr, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
RemoteGDB::removeSoftBreak(Addr addr, size_t len)
|
BaseRemoteGDB::removeSoftBreak(Addr addr, size_t len)
|
||||||
{
|
{
|
||||||
if (len != sizeof(MachInst))
|
if (len != sizeof(MachInst))
|
||||||
panic("invalid length\n");
|
panic("invalid length\n");
|
||||||
|
@ -734,7 +534,7 @@ RemoteGDB::removeSoftBreak(Addr addr, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
RemoteGDB::insertHardBreak(Addr addr, size_t len)
|
BaseRemoteGDB::insertHardBreak(Addr addr, size_t len)
|
||||||
{
|
{
|
||||||
if (len != sizeof(MachInst))
|
if (len != sizeof(MachInst))
|
||||||
panic("invalid length\n");
|
panic("invalid length\n");
|
||||||
|
@ -751,7 +551,7 @@ RemoteGDB::insertHardBreak(Addr addr, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
RemoteGDB::removeHardBreak(Addr addr, size_t len)
|
BaseRemoteGDB::removeHardBreak(Addr addr, size_t len)
|
||||||
{
|
{
|
||||||
if (len != sizeof(MachInst))
|
if (len != sizeof(MachInst))
|
||||||
panic("invalid length\n");
|
panic("invalid length\n");
|
||||||
|
@ -771,8 +571,23 @@ RemoteGDB::removeHardBreak(Addr addr, size_t len)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BaseRemoteGDB::setTempBreakpoint(Addr bkpt)
|
||||||
|
{
|
||||||
|
DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", bkpt);
|
||||||
|
insertHardBreak(bkpt, sizeof(TheISA::MachInst));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BaseRemoteGDB::clearTempBreakpoint(Addr &bkpt)
|
||||||
|
{
|
||||||
|
DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", bkpt);
|
||||||
|
removeHardBreak(bkpt, sizeof(TheISA::MachInst));
|
||||||
|
bkpt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
break_type(char c)
|
BaseRemoteGDB::break_type(char c)
|
||||||
{
|
{
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case '0': return "software breakpoint";
|
case '0': return "software breakpoint";
|
||||||
|
@ -790,12 +605,12 @@ break_type(char c)
|
||||||
// makes sense to use POSIX errno values, because that is what the
|
// makes sense to use POSIX errno values, because that is what the
|
||||||
// gdb/remote.c functions want to return.
|
// gdb/remote.c functions want to return.
|
||||||
bool
|
bool
|
||||||
RemoteGDB::trap(int type)
|
BaseRemoteGDB::trap(int type)
|
||||||
{
|
{
|
||||||
uint64_t val;
|
uint64_t val;
|
||||||
size_t datalen, len;
|
size_t datalen, len;
|
||||||
char data[KGDB_BUFLEN + 1];
|
char data[GDBPacketBufLen + 1];
|
||||||
char buffer[sizeof(gdbregs) * 2 + 256];
|
char buffer[gdbregs.bytes() * 2 + 256];
|
||||||
const char *p;
|
const char *p;
|
||||||
char command, subcmd;
|
char command, subcmd;
|
||||||
string var;
|
string var;
|
||||||
|
@ -823,7 +638,7 @@ RemoteGDB::trap(int type)
|
||||||
active = true;
|
active = true;
|
||||||
else
|
else
|
||||||
// Tell remote host that an exception has occurred.
|
// Tell remote host that an exception has occurred.
|
||||||
snprintf((char *)buffer, sizeof(buffer), "S%02x", signal(type));
|
snprintf((char *)buffer, sizeof(buffer), "S%02x", type);
|
||||||
send(buffer);
|
send(buffer);
|
||||||
|
|
||||||
// Stick frame regs into our reg cache.
|
// Stick frame regs into our reg cache.
|
||||||
|
@ -837,24 +652,25 @@ RemoteGDB::trap(int type)
|
||||||
p = data + 1;
|
p = data + 1;
|
||||||
switch (command) {
|
switch (command) {
|
||||||
|
|
||||||
case KGDB_SIGNAL:
|
case GDBSignal:
|
||||||
// if this command came from a running gdb, answer it --
|
// if this command came from a running gdb, answer it --
|
||||||
// the other guy has no way of knowing if we're in or out
|
// the other guy has no way of knowing if we're in or out
|
||||||
// of this loop when he issues a "remote-signal".
|
// of this loop when he issues a "remote-signal".
|
||||||
snprintf((char *)buffer, sizeof(buffer), "S%02x", signal(type));
|
snprintf((char *)buffer, sizeof(buffer),
|
||||||
|
"S%02x", type);
|
||||||
send(buffer);
|
send(buffer);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case KGDB_REG_R:
|
case GDBRegR:
|
||||||
if (2 * sizeof(gdbregs) > sizeof(buffer))
|
if (2 * gdbregs.bytes() > sizeof(buffer))
|
||||||
panic("buffer too small");
|
panic("buffer too small");
|
||||||
|
|
||||||
mem2hex(buffer, gdbregs, sizeof(gdbregs));
|
mem2hex(buffer, gdbregs.regs, gdbregs.bytes());
|
||||||
send(buffer);
|
send(buffer);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case KGDB_REG_W:
|
case GDBRegW:
|
||||||
p = hex2mem(gdbregs, p, sizeof(gdbregs));
|
p = hex2mem(gdbregs.regs, p, gdbregs.bytes());
|
||||||
if (p == NULL || *p != '\0')
|
if (p == NULL || *p != '\0')
|
||||||
send("E01");
|
send("E01");
|
||||||
else {
|
else {
|
||||||
|
@ -864,7 +680,7 @@ RemoteGDB::trap(int type)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
case KGDB_SET_REG:
|
case GDBSetReg:
|
||||||
val = hex2i(&p);
|
val = hex2i(&p);
|
||||||
if (*p++ != '=') {
|
if (*p++ != '=') {
|
||||||
send("E01");
|
send("E01");
|
||||||
|
@ -875,14 +691,14 @@ RemoteGDB::trap(int type)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
gdbregs[val] = hex2i(&p);
|
gdbregs.regs[val] = hex2i(&p);
|
||||||
setregs();
|
setregs();
|
||||||
send("OK");
|
send("OK");
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case KGDB_MEM_R:
|
case GDBMemR:
|
||||||
val = hex2i(&p);
|
val = hex2i(&p);
|
||||||
if (*p++ != ',') {
|
if (*p++ != ',') {
|
||||||
send("E02");
|
send("E02");
|
||||||
|
@ -914,7 +730,7 @@ RemoteGDB::trap(int type)
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case KGDB_MEM_W:
|
case GDBMemW:
|
||||||
val = hex2i(&p);
|
val = hex2i(&p);
|
||||||
if (*p++ != ',') {
|
if (*p++ != ',') {
|
||||||
send("E06");
|
send("E06");
|
||||||
|
@ -944,7 +760,7 @@ RemoteGDB::trap(int type)
|
||||||
send("E0B");
|
send("E0B");
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case KGDB_SET_THREAD:
|
case GDBSetThread:
|
||||||
subcmd = *p++;
|
subcmd = *p++;
|
||||||
val = hex2i(&p);
|
val = hex2i(&p);
|
||||||
if (val == 0)
|
if (val == 0)
|
||||||
|
@ -953,14 +769,14 @@ RemoteGDB::trap(int type)
|
||||||
send("E01");
|
send("E01");
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case KGDB_DETACH:
|
case GDBDetach:
|
||||||
case KGDB_KILL:
|
case GDBKill:
|
||||||
active = false;
|
active = false;
|
||||||
clearSingleStep();
|
clearSingleStep();
|
||||||
detach();
|
detach();
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
case KGDB_ASYNC_CONT:
|
case GDBAsyncCont:
|
||||||
subcmd = hex2i(&p);
|
subcmd = hex2i(&p);
|
||||||
if (*p++ == ';') {
|
if (*p++ == ';') {
|
||||||
val = hex2i(&p);
|
val = hex2i(&p);
|
||||||
|
@ -970,7 +786,7 @@ RemoteGDB::trap(int type)
|
||||||
clearSingleStep();
|
clearSingleStep();
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
case KGDB_CONT:
|
case GDBCont:
|
||||||
if (p - data < datalen) {
|
if (p - data < datalen) {
|
||||||
val = hex2i(&p);
|
val = hex2i(&p);
|
||||||
context->setPC(val);
|
context->setPC(val);
|
||||||
|
@ -979,7 +795,7 @@ RemoteGDB::trap(int type)
|
||||||
clearSingleStep();
|
clearSingleStep();
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
case KGDB_ASYNC_STEP:
|
case GDBAsyncStep:
|
||||||
subcmd = hex2i(&p);
|
subcmd = hex2i(&p);
|
||||||
if (*p++ == ';') {
|
if (*p++ == ';') {
|
||||||
val = hex2i(&p);
|
val = hex2i(&p);
|
||||||
|
@ -989,7 +805,7 @@ RemoteGDB::trap(int type)
|
||||||
setSingleStep();
|
setSingleStep();
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
case KGDB_STEP:
|
case GDBStep:
|
||||||
if (p - data < datalen) {
|
if (p - data < datalen) {
|
||||||
val = hex2i(&p);
|
val = hex2i(&p);
|
||||||
context->setPC(val);
|
context->setPC(val);
|
||||||
|
@ -998,7 +814,7 @@ RemoteGDB::trap(int type)
|
||||||
setSingleStep();
|
setSingleStep();
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
case KGDB_CLR_HW_BKPT:
|
case GDBClrHwBkpt:
|
||||||
subcmd = *p++;
|
subcmd = *p++;
|
||||||
if (*p++ != ',') send("E0D");
|
if (*p++ != ',') send("E0D");
|
||||||
val = hex2i(&p);
|
val = hex2i(&p);
|
||||||
|
@ -1030,7 +846,7 @@ RemoteGDB::trap(int type)
|
||||||
send(ret ? "OK" : "E0C");
|
send(ret ? "OK" : "E0C");
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case KGDB_SET_HW_BKPT:
|
case GDBSetHwBkpt:
|
||||||
subcmd = *p++;
|
subcmd = *p++;
|
||||||
if (*p++ != ',') send("E0D");
|
if (*p++ != ',') send("E0D");
|
||||||
val = hex2i(&p);
|
val = hex2i(&p);
|
||||||
|
@ -1062,7 +878,7 @@ RemoteGDB::trap(int type)
|
||||||
send(ret ? "OK" : "E0C");
|
send(ret ? "OK" : "E0C");
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case KGDB_QUERY_VAR:
|
case GDBQueryVar:
|
||||||
var = string(p, datalen - 1);
|
var = string(p, datalen - 1);
|
||||||
if (var == "C")
|
if (var == "C")
|
||||||
send("QC0");
|
send("QC0");
|
||||||
|
@ -1070,17 +886,17 @@ RemoteGDB::trap(int type)
|
||||||
send("");
|
send("");
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case KGDB_SET_BAUD:
|
case GDBSetBaud:
|
||||||
case KGDB_SET_BREAK:
|
case GDBSetBreak:
|
||||||
case KGDB_DEBUG:
|
case GDBDebug:
|
||||||
case KGDB_CYCLE_STEP:
|
case GDBCycleStep:
|
||||||
case KGDB_SIG_CYCLE_STEP:
|
case GDBSigCycleStep:
|
||||||
case KGDB_READ_REG:
|
case GDBReadReg:
|
||||||
case KGDB_SET_VAR:
|
case GDBSetVar:
|
||||||
case KGDB_RESET:
|
case GDBReset:
|
||||||
case KGDB_THREAD_ALIVE:
|
case GDBThreadAlive:
|
||||||
case KGDB_TARGET_EXIT:
|
case GDBTargetExit:
|
||||||
case KGDB_BINARY_DLOAD:
|
case GDBBinaryDload:
|
||||||
// Unsupported command
|
// Unsupported command
|
||||||
DPRINTF(GDBMisc, "Unsupported command: %s\n",
|
DPRINTF(GDBMisc, "Unsupported command: %s\n",
|
||||||
gdb_command(command));
|
gdb_command(command));
|
||||||
|
@ -1106,7 +922,7 @@ RemoteGDB::trap(int type)
|
||||||
// Convert a hex digit into an integer.
|
// Convert a hex digit into an integer.
|
||||||
// This returns -1 if the argument passed is no valid hex digit.
|
// This returns -1 if the argument passed is no valid hex digit.
|
||||||
int
|
int
|
||||||
digit2i(char c)
|
BaseRemoteGDB::digit2i(char c)
|
||||||
{
|
{
|
||||||
if (c >= '0' && c <= '9')
|
if (c >= '0' && c <= '9')
|
||||||
return (c - '0');
|
return (c - '0');
|
||||||
|
@ -1121,14 +937,14 @@ digit2i(char c)
|
||||||
|
|
||||||
// Convert the low 4 bits of an integer into an hex digit.
|
// Convert the low 4 bits of an integer into an hex digit.
|
||||||
char
|
char
|
||||||
i2digit(int n)
|
BaseRemoteGDB::i2digit(int n)
|
||||||
{
|
{
|
||||||
return ("0123456789abcdef"[n & 0x0f]);
|
return ("0123456789abcdef"[n & 0x0f]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a byte array into an hex string.
|
// Convert a byte array into an hex string.
|
||||||
void
|
void
|
||||||
mem2hex(void *vdst, const void *vsrc, int len)
|
BaseRemoteGDB::mem2hex(void *vdst, const void *vsrc, int len)
|
||||||
{
|
{
|
||||||
char *dst = (char *)vdst;
|
char *dst = (char *)vdst;
|
||||||
const char *src = (const char *)vsrc;
|
const char *src = (const char *)vsrc;
|
||||||
|
@ -1145,7 +961,7 @@ mem2hex(void *vdst, const void *vsrc, int len)
|
||||||
// hex digit. If the string ends in the middle of a byte, NULL is
|
// hex digit. If the string ends in the middle of a byte, NULL is
|
||||||
// returned.
|
// returned.
|
||||||
const char *
|
const char *
|
||||||
hex2mem(void *vdst, const char *src, int maxlen)
|
BaseRemoteGDB::hex2mem(void *vdst, const char *src, int maxlen)
|
||||||
{
|
{
|
||||||
char *dst = (char *)vdst;
|
char *dst = (char *)vdst;
|
||||||
int msb, lsb;
|
int msb, lsb;
|
||||||
|
@ -1166,7 +982,7 @@ hex2mem(void *vdst, const char *src, int maxlen)
|
||||||
// This returns a pointer to the character following the last valid
|
// This returns a pointer to the character following the last valid
|
||||||
// hex digit.
|
// hex digit.
|
||||||
Addr
|
Addr
|
||||||
hex2i(const char **srcp)
|
BaseRemoteGDB::hex2i(const char **srcp)
|
||||||
{
|
{
|
||||||
const char *src = *srcp;
|
const char *src = *srcp;
|
||||||
Addr r = 0;
|
Addr r = 0;
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "arch/types.hh"
|
#include "arch/types.hh"
|
||||||
#include "base/kgdb.h"
|
|
||||||
#include "cpu/pc_event.hh"
|
#include "cpu/pc_event.hh"
|
||||||
#include "base/pollevent.hh"
|
#include "base/pollevent.hh"
|
||||||
#include "base/socket.hh"
|
#include "base/socket.hh"
|
||||||
|
@ -44,22 +43,72 @@ class ThreadContext;
|
||||||
class PhysicalMemory;
|
class PhysicalMemory;
|
||||||
|
|
||||||
class GDBListener;
|
class GDBListener;
|
||||||
class RemoteGDB
|
|
||||||
|
enum GDBCommands
|
||||||
|
{
|
||||||
|
GDBSignal = '?', // last signal
|
||||||
|
GDBSetBaud = 'b', // set baud (depracated)
|
||||||
|
GDBSetBreak = 'B', // set breakpoint (depracated)
|
||||||
|
GDBCont = 'c', // resume
|
||||||
|
GDBAsyncCont = 'C', // continue with signal
|
||||||
|
GDBDebug = 'd', // toggle debug flags (deprecated)
|
||||||
|
GDBDetach = 'D', // detach remote gdb
|
||||||
|
GDBRegR = 'g', // read general registers
|
||||||
|
GDBRegW = 'G', // write general registers
|
||||||
|
GDBSetThread = 'H', // set thread
|
||||||
|
GDBCycleStep = 'i', // step a single cycle
|
||||||
|
GDBSigCycleStep = 'I', // signal then cycle step
|
||||||
|
GDBKill = 'k', // kill program
|
||||||
|
GDBMemR = 'm', // read memory
|
||||||
|
GDBMemW = 'M', // write memory
|
||||||
|
GDBReadReg = 'p', // read register
|
||||||
|
GDBSetReg = 'P', // write register
|
||||||
|
GDBQueryVar = 'q', // query variable
|
||||||
|
GDBSetVar = 'Q', // set variable
|
||||||
|
GDBReset = 'r', // reset system. (Deprecated)
|
||||||
|
GDBStep = 's', // step
|
||||||
|
GDBAsyncStep = 'S', // signal and step
|
||||||
|
GDBThreadAlive = 'T', // find out if the thread is alive
|
||||||
|
GDBTargetExit = 'W', // target exited
|
||||||
|
GDBBinaryDload = 'X', // write memory
|
||||||
|
GDBClrHwBkpt = 'z', // remove breakpoint or watchpoint
|
||||||
|
GDBSetHwBkpt = 'Z' // insert breakpoint or watchpoint
|
||||||
|
};
|
||||||
|
|
||||||
|
const char GDBStart = '$';
|
||||||
|
const char GDBEnd = '#';
|
||||||
|
const char GDBGoodP = '+';
|
||||||
|
const char GDBBadP = '-';
|
||||||
|
|
||||||
|
const int GDBPacketBufLen = 1024;
|
||||||
|
|
||||||
|
class BaseRemoteGDB
|
||||||
{
|
{
|
||||||
protected:
|
|
||||||
typedef TheISA::MachInst MachInst;
|
|
||||||
private:
|
private:
|
||||||
friend void debugger();
|
friend void debugger();
|
||||||
friend class GDBListener;
|
friend class GDBListener;
|
||||||
|
|
||||||
|
//Helper functions
|
||||||
|
protected:
|
||||||
|
int digit2i(char);
|
||||||
|
char i2digit(int);
|
||||||
|
Addr hex2i(const char **);
|
||||||
|
//Address formats, break types, and gdb commands may change
|
||||||
|
//between architectures, so they're defined as virtual
|
||||||
|
//functions.
|
||||||
|
virtual void mem2hex(void *, const void *, int);
|
||||||
|
virtual const char * hex2mem(void *, const char *, int);
|
||||||
|
virtual const char * break_type(char c);
|
||||||
|
virtual const char * gdb_command(char cmd);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
class Event : public PollEvent
|
class Event : public PollEvent
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
RemoteGDB *gdb;
|
BaseRemoteGDB *gdb;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Event(RemoteGDB *g, int fd, int e);
|
Event(BaseRemoteGDB *g, int fd, int e);
|
||||||
void process(int revent);
|
void process(int revent);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -69,8 +118,8 @@ class RemoteGDB
|
||||||
int number;
|
int number;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
//The socket commands come in through
|
||||||
int fd;
|
int fd;
|
||||||
uint64_t gdbregs[KGDB_NUMREGS];
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
#ifdef notyet
|
#ifdef notyet
|
||||||
|
@ -83,6 +132,24 @@ class RemoteGDB
|
||||||
PhysicalMemory *pmem;
|
PhysicalMemory *pmem;
|
||||||
ThreadContext *context;
|
ThreadContext *context;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
class GdbRegCache
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GdbRegCache(size_t newSize) : regs(new uint64_t[newSize]), size(newSize)
|
||||||
|
{}
|
||||||
|
~GdbRegCache()
|
||||||
|
{
|
||||||
|
delete [] regs;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t * regs;
|
||||||
|
size_t size;
|
||||||
|
size_t bytes() { return size * sizeof(uint64_t); }
|
||||||
|
};
|
||||||
|
|
||||||
|
GdbRegCache gdbregs;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint8_t getbyte();
|
uint8_t getbyte();
|
||||||
void putbyte(uint8_t b);
|
void putbyte(uint8_t b);
|
||||||
|
@ -92,15 +159,15 @@ class RemoteGDB
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Machine memory
|
// Machine memory
|
||||||
bool read(Addr addr, size_t size, char *data);
|
virtual bool read(Addr addr, size_t size, char *data);
|
||||||
bool write(Addr addr, size_t size, const char *data);
|
virtual bool write(Addr addr, size_t size, const char *data);
|
||||||
|
|
||||||
template <class T> T read(Addr addr);
|
template <class T> T read(Addr addr);
|
||||||
template <class T> void write(Addr addr, T data);
|
template <class T> void write(Addr addr, T data);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RemoteGDB(System *system, ThreadContext *context);
|
BaseRemoteGDB(System *system, ThreadContext *context, size_t cacheSize);
|
||||||
~RemoteGDB();
|
virtual ~BaseRemoteGDB();
|
||||||
|
|
||||||
void replaceThreadContext(ThreadContext *tc) { context = tc; }
|
void replaceThreadContext(ThreadContext *tc) { context = tc; }
|
||||||
|
|
||||||
|
@ -108,16 +175,15 @@ class RemoteGDB
|
||||||
void detach();
|
void detach();
|
||||||
bool isattached();
|
bool isattached();
|
||||||
|
|
||||||
bool acc(Addr addr, size_t len);
|
virtual bool acc(Addr addr, size_t len) = 0;
|
||||||
static int signal(int type);
|
|
||||||
bool trap(int type);
|
bool trap(int type);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void getregs();
|
virtual void getregs() = 0;
|
||||||
void setregs();
|
virtual void setregs() = 0;
|
||||||
|
|
||||||
void clearSingleStep();
|
virtual void clearSingleStep() = 0;
|
||||||
void setSingleStep();
|
virtual void setSingleStep() = 0;
|
||||||
|
|
||||||
PCEventQueue *getPcEventQueue();
|
PCEventQueue *getPcEventQueue();
|
||||||
|
|
||||||
|
@ -125,13 +191,13 @@ class RemoteGDB
|
||||||
class HardBreakpoint : public PCEvent
|
class HardBreakpoint : public PCEvent
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
RemoteGDB *gdb;
|
BaseRemoteGDB *gdb;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int refcount;
|
int refcount;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HardBreakpoint(RemoteGDB *_gdb, Addr addr);
|
HardBreakpoint(BaseRemoteGDB *_gdb, Addr addr);
|
||||||
std::string name() { return gdb->name() + ".hwbkpt"; }
|
std::string name() { return gdb->name() + ".hwbkpt"; }
|
||||||
|
|
||||||
virtual void process(ThreadContext *tc);
|
virtual void process(ThreadContext *tc);
|
||||||
|
@ -148,18 +214,8 @@ class RemoteGDB
|
||||||
bool removeHardBreak(Addr addr, size_t len);
|
bool removeHardBreak(Addr addr, size_t len);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct TempBreakpoint {
|
void clearTempBreakpoint(Addr &bkpt);
|
||||||
Addr address; // set here
|
void setTempBreakpoint(Addr bkpt);
|
||||||
MachInst bkpt_inst; // saved instruction at bkpt
|
|
||||||
int init_count; // number of times to skip bkpt
|
|
||||||
int count; // current count
|
|
||||||
};
|
|
||||||
|
|
||||||
TempBreakpoint notTakenBkpt;
|
|
||||||
TempBreakpoint takenBkpt;
|
|
||||||
|
|
||||||
void clearTempBreakpoint(TempBreakpoint &bkpt);
|
|
||||||
void setTempBreakpoint(TempBreakpoint &bkpt, Addr addr);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::string name();
|
std::string name();
|
||||||
|
@ -167,7 +223,7 @@ class RemoteGDB
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T
|
inline T
|
||||||
RemoteGDB::read(Addr addr)
|
BaseRemoteGDB::read(Addr addr)
|
||||||
{
|
{
|
||||||
T temp;
|
T temp;
|
||||||
read(addr, sizeof(T), (char *)&temp);
|
read(addr, sizeof(T), (char *)&temp);
|
||||||
|
@ -176,7 +232,7 @@ RemoteGDB::read(Addr addr)
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline void
|
inline void
|
||||||
RemoteGDB::write(Addr addr, T data)
|
BaseRemoteGDB::write(Addr addr, T data)
|
||||||
{ write(addr, sizeof(T), (const char *)&data); }
|
{ write(addr, sizeof(T), (const char *)&data); }
|
||||||
|
|
||||||
class GDBListener
|
class GDBListener
|
||||||
|
@ -197,11 +253,11 @@ class GDBListener
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ListenSocket listener;
|
ListenSocket listener;
|
||||||
RemoteGDB *gdb;
|
BaseRemoteGDB *gdb;
|
||||||
int port;
|
int port;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GDBListener(RemoteGDB *g, int p);
|
GDBListener(BaseRemoteGDB *g, int p);
|
||||||
~GDBListener();
|
~GDBListener();
|
||||||
|
|
||||||
void accept();
|
void accept();
|
||||||
|
|
|
@ -696,7 +696,7 @@ class ScalarBase : public DataAccess
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/** The storage of this stat. */
|
/** The storage of this stat. */
|
||||||
char storage[sizeof(Storage)];
|
char storage[sizeof(Storage)] __attribute__ ((aligned (8)));
|
||||||
|
|
||||||
/** The parameters for this stat. */
|
/** The parameters for this stat. */
|
||||||
Params params;
|
Params params;
|
||||||
|
@ -1637,7 +1637,7 @@ class DistBase : public DataAccess
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/** The storage for this stat. */
|
/** The storage for this stat. */
|
||||||
char storage[sizeof(Storage)];
|
char storage[sizeof(Storage)] __attribute__ ((aligned (8)));
|
||||||
|
|
||||||
/** The parameters for this stat. */
|
/** The parameters for this stat. */
|
||||||
Params params;
|
Params params;
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace Stats {
|
||||||
* Define the storage for format flags.
|
* Define the storage for format flags.
|
||||||
* @todo Can probably shrink this.
|
* @todo Can probably shrink this.
|
||||||
*/
|
*/
|
||||||
typedef u_int32_t StatFlags;
|
typedef uint32_t StatFlags;
|
||||||
|
|
||||||
/** Nothing extra to print. */
|
/** Nothing extra to print. */
|
||||||
const StatFlags none = 0x00000000;
|
const StatFlags none = 0x00000000;
|
||||||
|
|
|
@ -65,4 +65,48 @@ Time operator-(const Time &l, const Time &r);
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &out, const Time &time);
|
std::ostream &operator<<(std::ostream &out, const Time &time);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1982, 1986, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)time.h 8.2 (Berkeley) 7/10/94
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(__sun__)
|
||||||
|
#define timersub(tvp, uvp, vvp) \
|
||||||
|
do { \
|
||||||
|
(vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
|
||||||
|
(vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
|
||||||
|
if ((vvp)->tv_usec < 0) { \
|
||||||
|
(vvp)->tv_sec--; \
|
||||||
|
(vvp)->tv_usec += 1000000; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // __SIM_TIME_HH__
|
#endif // __SIM_TIME_HH__
|
||||||
|
|
|
@ -168,11 +168,6 @@ BaseCPU::BaseCPU(Params *p)
|
||||||
p->max_loads_all_threads, *counter);
|
p->max_loads_all_threads, *counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
|
||||||
memset(interrupts, 0, sizeof(interrupts));
|
|
||||||
intstatus = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
functionTracingEnabled = false;
|
functionTracingEnabled = false;
|
||||||
if (p->functionTrace) {
|
if (p->functionTrace) {
|
||||||
functionTraceStream = simout.find(csprintf("ftrace.%s", name()));
|
functionTraceStream = simout.find(csprintf("ftrace.%s", name()));
|
||||||
|
@ -259,6 +254,26 @@ BaseCPU::regStats()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Tick
|
||||||
|
BaseCPU::nextCycle()
|
||||||
|
{
|
||||||
|
Tick next_tick = curTick + clock - 1;
|
||||||
|
next_tick -= (next_tick % clock);
|
||||||
|
return next_tick;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tick
|
||||||
|
BaseCPU::nextCycle(Tick begin_tick)
|
||||||
|
{
|
||||||
|
Tick next_tick = begin_tick;
|
||||||
|
|
||||||
|
while (next_tick < curTick)
|
||||||
|
next_tick += clock;
|
||||||
|
|
||||||
|
next_tick -= (next_tick % clock);
|
||||||
|
assert(next_tick >= curTick);
|
||||||
|
return next_tick;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BaseCPU::registerThreadContexts()
|
BaseCPU::registerThreadContexts()
|
||||||
|
@ -314,9 +329,7 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
for (int i = 0; i < TheISA::NumInterruptLevels; ++i)
|
interrupts = oldCPU->interrupts;
|
||||||
interrupts[i] = oldCPU->interrupts[i];
|
|
||||||
intstatus = oldCPU->intstatus;
|
|
||||||
checkInterrupts = oldCPU->checkInterrupts;
|
checkInterrupts = oldCPU->checkInterrupts;
|
||||||
|
|
||||||
for (int i = 0; i < threadContexts.size(); ++i)
|
for (int i = 0; i < threadContexts.size(); ++i)
|
||||||
|
@ -348,57 +361,33 @@ BaseCPU::ProfileEvent::process()
|
||||||
void
|
void
|
||||||
BaseCPU::post_interrupt(int int_num, int index)
|
BaseCPU::post_interrupt(int int_num, int index)
|
||||||
{
|
{
|
||||||
DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
|
|
||||||
|
|
||||||
if (int_num < 0 || int_num >= TheISA::NumInterruptLevels)
|
|
||||||
panic("int_num out of bounds\n");
|
|
||||||
|
|
||||||
if (index < 0 || index >= sizeof(uint64_t) * 8)
|
|
||||||
panic("int_num out of bounds\n");
|
|
||||||
|
|
||||||
checkInterrupts = true;
|
checkInterrupts = true;
|
||||||
interrupts[int_num] |= 1 << index;
|
interrupts.post(int_num, index);
|
||||||
intstatus |= (ULL(1) << int_num);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BaseCPU::clear_interrupt(int int_num, int index)
|
BaseCPU::clear_interrupt(int int_num, int index)
|
||||||
{
|
{
|
||||||
DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
|
interrupts.clear(int_num, index);
|
||||||
|
|
||||||
if (int_num < 0 || int_num >= TheISA::NumInterruptLevels)
|
|
||||||
panic("int_num out of bounds\n");
|
|
||||||
|
|
||||||
if (index < 0 || index >= sizeof(uint64_t) * 8)
|
|
||||||
panic("int_num out of bounds\n");
|
|
||||||
|
|
||||||
interrupts[int_num] &= ~(1 << index);
|
|
||||||
if (interrupts[int_num] == 0)
|
|
||||||
intstatus &= ~(ULL(1) << int_num);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BaseCPU::clear_interrupts()
|
BaseCPU::clear_interrupts()
|
||||||
{
|
{
|
||||||
DPRINTF(Interrupt, "Interrupts all cleared\n");
|
interrupts.clear_all();
|
||||||
|
|
||||||
memset(interrupts, 0, sizeof(interrupts));
|
|
||||||
intstatus = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BaseCPU::serialize(std::ostream &os)
|
BaseCPU::serialize(std::ostream &os)
|
||||||
{
|
{
|
||||||
SERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels);
|
interrupts.serialize(os);
|
||||||
SERIALIZE_SCALAR(intstatus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BaseCPU::unserialize(Checkpoint *cp, const std::string §ion)
|
BaseCPU::unserialize(Checkpoint *cp, const std::string §ion)
|
||||||
{
|
{
|
||||||
UNSERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels);
|
interrupts.unserialize(cp, section);
|
||||||
UNSERIALIZE_SCALAR(intstatus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // FULL_SYSTEM
|
#endif // FULL_SYSTEM
|
||||||
|
|
|
@ -40,6 +40,10 @@
|
||||||
#include "mem/mem_object.hh"
|
#include "mem/mem_object.hh"
|
||||||
#include "arch/isa_traits.hh"
|
#include "arch/isa_traits.hh"
|
||||||
|
|
||||||
|
#if FULL_SYSTEM
|
||||||
|
#include "arch/interrupts.hh"
|
||||||
|
#endif
|
||||||
|
|
||||||
class BranchPred;
|
class BranchPred;
|
||||||
class CheckerCPU;
|
class CheckerCPU;
|
||||||
class ThreadContext;
|
class ThreadContext;
|
||||||
|
@ -73,10 +77,25 @@ class BaseCPU : public MemObject
|
||||||
inline Tick cycles(int numCycles) const { return clock * numCycles; }
|
inline Tick cycles(int numCycles) const { return clock * numCycles; }
|
||||||
inline Tick curCycle() const { return curTick / clock; }
|
inline Tick curCycle() const { return curTick / clock; }
|
||||||
|
|
||||||
|
/** The next cycle the CPU should be scheduled, given a cache
|
||||||
|
* access or quiesce event returning on this cycle. This function
|
||||||
|
* may return curTick if the CPU should run on the current cycle.
|
||||||
|
*/
|
||||||
|
Tick nextCycle();
|
||||||
|
|
||||||
|
/** The next cycle the CPU should be scheduled, given a cache
|
||||||
|
* access or quiesce event returning on the given Tick. This
|
||||||
|
* function may return curTick if the CPU should run on the
|
||||||
|
* current cycle.
|
||||||
|
* @param begin_tick The tick that the event is completing on.
|
||||||
|
*/
|
||||||
|
Tick nextCycle(Tick begin_tick);
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
protected:
|
protected:
|
||||||
uint64_t interrupts[TheISA::NumInterruptLevels];
|
// uint64_t interrupts[TheISA::NumInterruptLevels];
|
||||||
uint64_t intstatus;
|
// uint64_t intstatus;
|
||||||
|
TheISA::Interrupts interrupts;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void post_interrupt(int int_num, int index);
|
virtual void post_interrupt(int int_num, int index);
|
||||||
|
@ -84,15 +103,8 @@ class BaseCPU : public MemObject
|
||||||
virtual void clear_interrupts();
|
virtual void clear_interrupts();
|
||||||
bool checkInterrupts;
|
bool checkInterrupts;
|
||||||
|
|
||||||
bool check_interrupt(int int_num) const {
|
bool check_interrupts(ThreadContext * tc) const
|
||||||
if (int_num > TheISA::NumInterruptLevels)
|
{ return interrupts.check_interrupts(tc); }
|
||||||
panic("int_num out of bounds\n");
|
|
||||||
|
|
||||||
return interrupts[int_num] != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool check_interrupts() const { return intstatus != 0; }
|
|
||||||
uint64_t intr_status() const { return intstatus; }
|
|
||||||
|
|
||||||
class ProfileEvent : public Event
|
class ProfileEvent : public Event
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,8 +38,8 @@
|
||||||
#include "cpu/thread_context.hh"
|
#include "cpu/thread_context.hh"
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
|
#include "arch/kernel_stats.hh"
|
||||||
#include "arch/vtophys.hh"
|
#include "arch/vtophys.hh"
|
||||||
#include "kern/kernel_stats.hh"
|
|
||||||
#endif // FULL_SYSTEM
|
#endif // FULL_SYSTEM
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -72,6 +72,12 @@ CheckerCPU::CheckerCPU(Params *p)
|
||||||
systemPtr = NULL;
|
systemPtr = NULL;
|
||||||
#else
|
#else
|
||||||
process = p->process;
|
process = p->process;
|
||||||
|
thread = new SimpleThread(this, /* thread_num */ 0, process,
|
||||||
|
/* asid */ 0);
|
||||||
|
|
||||||
|
thread->setStatus(ThreadContext::Suspended);
|
||||||
|
tc = thread->getTC();
|
||||||
|
threadContexts.push_back(tc);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
result.integer = 0;
|
result.integer = 0;
|
||||||
|
@ -81,20 +87,6 @@ CheckerCPU::~CheckerCPU()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
CheckerCPU::setMemory(MemObject *mem)
|
|
||||||
{
|
|
||||||
#if !FULL_SYSTEM
|
|
||||||
memPtr = mem;
|
|
||||||
thread = new SimpleThread(this, /* thread_num */ 0, process,
|
|
||||||
/* asid */ 0, mem);
|
|
||||||
|
|
||||||
thread->setStatus(ThreadContext::Suspended);
|
|
||||||
tc = thread->getTC();
|
|
||||||
threadContexts.push_back(tc);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CheckerCPU::setSystem(System *system)
|
CheckerCPU::setSystem(System *system)
|
||||||
{
|
{
|
||||||
|
|
|
@ -47,9 +47,12 @@
|
||||||
|
|
||||||
// forward declarations
|
// forward declarations
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
|
namespace TheISA
|
||||||
|
{
|
||||||
|
class ITB;
|
||||||
|
class DTB;
|
||||||
|
}
|
||||||
class Processor;
|
class Processor;
|
||||||
class AlphaITB;
|
|
||||||
class AlphaDTB;
|
|
||||||
class PhysicalMemory;
|
class PhysicalMemory;
|
||||||
|
|
||||||
class RemoteGDB;
|
class RemoteGDB;
|
||||||
|
@ -96,8 +99,8 @@ class CheckerCPU : public BaseCPU
|
||||||
struct Params : public BaseCPU::Params
|
struct Params : public BaseCPU::Params
|
||||||
{
|
{
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
AlphaITB *itb;
|
TheISA::ITB *itb;
|
||||||
AlphaDTB *dtb;
|
TheISA::DTB *dtb;
|
||||||
#else
|
#else
|
||||||
Process *process;
|
Process *process;
|
||||||
#endif
|
#endif
|
||||||
|
@ -112,10 +115,6 @@ class CheckerCPU : public BaseCPU
|
||||||
|
|
||||||
Process *process;
|
Process *process;
|
||||||
|
|
||||||
void setMemory(MemObject *mem);
|
|
||||||
|
|
||||||
MemObject *memPtr;
|
|
||||||
|
|
||||||
void setSystem(System *system);
|
void setSystem(System *system);
|
||||||
|
|
||||||
System *systemPtr;
|
System *systemPtr;
|
||||||
|
@ -140,8 +139,8 @@ class CheckerCPU : public BaseCPU
|
||||||
|
|
||||||
ThreadContext *tc;
|
ThreadContext *tc;
|
||||||
|
|
||||||
AlphaITB *itb;
|
TheISA::ITB *itb;
|
||||||
AlphaDTB *dtb;
|
TheISA::DTB *dtb;
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
Addr dbg_vtophys(Addr addr);
|
Addr dbg_vtophys(Addr addr);
|
||||||
|
@ -301,19 +300,19 @@ class CheckerCPU : public BaseCPU
|
||||||
return thread->readMiscReg(misc_reg);
|
return thread->readMiscReg(misc_reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
|
MiscReg readMiscRegWithEffect(int misc_reg)
|
||||||
{
|
{
|
||||||
return thread->readMiscRegWithEffect(misc_reg, fault);
|
return thread->readMiscRegWithEffect(misc_reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault setMiscReg(int misc_reg, const MiscReg &val)
|
void setMiscReg(int misc_reg, const MiscReg &val)
|
||||||
{
|
{
|
||||||
result.integer = val;
|
result.integer = val;
|
||||||
miscRegIdxs.push(misc_reg);
|
miscRegIdxs.push(misc_reg);
|
||||||
return thread->setMiscReg(misc_reg, val);
|
return thread->setMiscReg(misc_reg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
|
void setMiscRegWithEffect(int misc_reg, const MiscReg &val)
|
||||||
{
|
{
|
||||||
miscRegIdxs.push(misc_reg);
|
miscRegIdxs.push(misc_reg);
|
||||||
return thread->setMiscRegWithEffect(misc_reg, val);
|
return thread->setMiscRegWithEffect(misc_reg, val);
|
||||||
|
@ -328,9 +327,6 @@ class CheckerCPU : public BaseCPU
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
Fault hwrei() { return thread->hwrei(); }
|
Fault hwrei() { return thread->hwrei(); }
|
||||||
int readIntrFlag() { return thread->readIntrFlag(); }
|
|
||||||
void setIntrFlag(int val) { thread->setIntrFlag(val); }
|
|
||||||
bool inPalMode() { return thread->inPalMode(); }
|
|
||||||
void ev5_trap(Fault fault) { fault->invoke(tc); }
|
void ev5_trap(Fault fault) { fault->invoke(tc); }
|
||||||
bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); }
|
bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); }
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -199,8 +199,13 @@ Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
|
||||||
// Checks both the machine instruction and the PC.
|
// Checks both the machine instruction and the PC.
|
||||||
validateInst(inst);
|
validateInst(inst);
|
||||||
|
|
||||||
|
#if THE_ISA == ALPHA_ISA
|
||||||
|
curStaticInst = StaticInst::decode(makeExtMI(machInst,
|
||||||
|
thread->readPC()));
|
||||||
|
#elif THE_ISA == SPARC_ISA
|
||||||
curStaticInst = StaticInst::decode(makeExtMI(machInst,
|
curStaticInst = StaticInst::decode(makeExtMI(machInst,
|
||||||
thread->getTC()));
|
thread->getTC()));
|
||||||
|
#endif
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
thread->setInst(machInst);
|
thread->setInst(machInst);
|
||||||
|
|
|
@ -37,8 +37,10 @@
|
||||||
#include "cpu/thread_context.hh"
|
#include "cpu/thread_context.hh"
|
||||||
|
|
||||||
class EndQuiesceEvent;
|
class EndQuiesceEvent;
|
||||||
namespace Kernel {
|
namespace TheISA {
|
||||||
class Statistics;
|
namespace Kernel {
|
||||||
|
class Statistics;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -87,11 +89,12 @@ class CheckerThreadContext : public ThreadContext
|
||||||
|
|
||||||
PhysicalMemory *getPhysMemPtr() { return actualTC->getPhysMemPtr(); }
|
PhysicalMemory *getPhysMemPtr() { return actualTC->getPhysMemPtr(); }
|
||||||
|
|
||||||
AlphaITB *getITBPtr() { return actualTC->getITBPtr(); }
|
TheISA::ITB *getITBPtr() { return actualTC->getITBPtr(); }
|
||||||
|
|
||||||
AlphaDTB *getDTBPtr() { return actualTC->getDTBPtr(); }
|
TheISA::DTB *getDTBPtr() { return actualTC->getDTBPtr(); }
|
||||||
|
|
||||||
Kernel::Statistics *getKernelStats() { return actualTC->getKernelStats(); }
|
TheISA::Kernel::Statistics *getKernelStats()
|
||||||
|
{ return actualTC->getKernelStats(); }
|
||||||
|
|
||||||
FunctionalPort *getPhysPort() { return actualTC->getPhysPort(); }
|
FunctionalPort *getPhysPort() { return actualTC->getPhysPort(); }
|
||||||
|
|
||||||
|
@ -248,19 +251,19 @@ class CheckerThreadContext : public ThreadContext
|
||||||
MiscReg readMiscReg(int misc_reg)
|
MiscReg readMiscReg(int misc_reg)
|
||||||
{ return actualTC->readMiscReg(misc_reg); }
|
{ return actualTC->readMiscReg(misc_reg); }
|
||||||
|
|
||||||
MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
|
MiscReg readMiscRegWithEffect(int misc_reg)
|
||||||
{ return actualTC->readMiscRegWithEffect(misc_reg, fault); }
|
{ return actualTC->readMiscRegWithEffect(misc_reg); }
|
||||||
|
|
||||||
Fault setMiscReg(int misc_reg, const MiscReg &val)
|
void setMiscReg(int misc_reg, const MiscReg &val)
|
||||||
{
|
{
|
||||||
checkerTC->setMiscReg(misc_reg, val);
|
checkerTC->setMiscReg(misc_reg, val);
|
||||||
return actualTC->setMiscReg(misc_reg, val);
|
actualTC->setMiscReg(misc_reg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
|
void setMiscRegWithEffect(int misc_reg, const MiscReg &val)
|
||||||
{
|
{
|
||||||
checkerTC->setMiscRegWithEffect(misc_reg, val);
|
checkerTC->setMiscRegWithEffect(misc_reg, val);
|
||||||
return actualTC->setMiscRegWithEffect(misc_reg, val);
|
actualTC->setMiscRegWithEffect(misc_reg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned readStCondFailures()
|
unsigned readStCondFailures()
|
||||||
|
@ -271,9 +274,6 @@ class CheckerThreadContext : public ThreadContext
|
||||||
checkerTC->setStCondFailures(sc_failures);
|
checkerTC->setStCondFailures(sc_failures);
|
||||||
actualTC->setStCondFailures(sc_failures);
|
actualTC->setStCondFailures(sc_failures);
|
||||||
}
|
}
|
||||||
#if FULL_SYSTEM
|
|
||||||
bool inPalMode() { return actualTC->inPalMode(); }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// @todo: Fix this!
|
// @todo: Fix this!
|
||||||
bool misspeculating() { return actualTC->misspeculating(); }
|
bool misspeculating() { return actualTC->misspeculating(); }
|
||||||
|
|
|
@ -44,7 +44,7 @@ class ThreadContext;
|
||||||
* */
|
* */
|
||||||
class CpuEvent : public Event
|
class CpuEvent : public Event
|
||||||
{
|
{
|
||||||
private:
|
protected:
|
||||||
/** type of global list of cpu events. */
|
/** type of global list of cpu events. */
|
||||||
typedef std::vector<CpuEvent *> CpuEventList;
|
typedef std::vector<CpuEvent *> CpuEventList;
|
||||||
|
|
||||||
|
|
|
@ -101,14 +101,14 @@ class ExecContext {
|
||||||
|
|
||||||
/** Reads a miscellaneous register, handling any architectural
|
/** Reads a miscellaneous register, handling any architectural
|
||||||
* side effects due to reading that register. */
|
* side effects due to reading that register. */
|
||||||
MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault);
|
MiscReg readMiscRegWithEffect(int misc_reg);
|
||||||
|
|
||||||
/** Sets a miscellaneous register. */
|
/** Sets a miscellaneous register. */
|
||||||
Fault setMiscReg(int misc_reg, const MiscReg &val);
|
void setMiscReg(int misc_reg, const MiscReg &val);
|
||||||
|
|
||||||
/** Sets a miscellaneous register, handling any architectural
|
/** Sets a miscellaneous register, handling any architectural
|
||||||
* side effects due to writing that register. */
|
* side effects due to writing that register. */
|
||||||
Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val);
|
void setMiscRegWithEffect(int misc_reg, const MiscReg &val);
|
||||||
|
|
||||||
/** Records the effective address of the instruction. Only valid
|
/** Records the effective address of the instruction. Only valid
|
||||||
* for memory ops. */
|
* for memory ops. */
|
||||||
|
@ -144,10 +144,6 @@ class ExecContext {
|
||||||
/** Somewhat Alpha-specific function that handles returning from
|
/** Somewhat Alpha-specific function that handles returning from
|
||||||
* an error or interrupt. */
|
* an error or interrupt. */
|
||||||
Fault hwrei();
|
Fault hwrei();
|
||||||
/** Reads the interrupt flags. */
|
|
||||||
int readIntrFlag();
|
|
||||||
/** Sets the interrupt flags to a value. */
|
|
||||||
void setIntrFlag(int val);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check for special simulator handling of specific PAL calls. If
|
* Check for special simulator handling of specific PAL calls. If
|
||||||
|
|
|
@ -33,8 +33,11 @@
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <sys/ipc.h>
|
||||||
|
#include <sys/shm.h>
|
||||||
|
|
||||||
#include "arch/regfile.hh"
|
#include "arch/regfile.hh"
|
||||||
|
#include "arch/utility.hh"
|
||||||
#include "base/loader/symtab.hh"
|
#include "base/loader/symtab.hh"
|
||||||
#include "cpu/base.hh"
|
#include "cpu/base.hh"
|
||||||
#include "cpu/exetrace.hh"
|
#include "cpu/exetrace.hh"
|
||||||
|
@ -44,10 +47,15 @@
|
||||||
|
|
||||||
//XXX This is temporary
|
//XXX This is temporary
|
||||||
#include "arch/isa_specific.hh"
|
#include "arch/isa_specific.hh"
|
||||||
|
#include "cpu/m5legion_interface.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace TheISA;
|
using namespace TheISA;
|
||||||
|
|
||||||
|
namespace Trace {
|
||||||
|
SharedData *shared_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Methods for the InstRecord object
|
// Methods for the InstRecord object
|
||||||
|
@ -75,23 +83,19 @@ Trace::InstRecord::dump(ostream &outs)
|
||||||
uint64_t newVal;
|
uint64_t newVal;
|
||||||
static const char * prefixes[4] = {"G", "O", "L", "I"};
|
static const char * prefixes[4] = {"G", "O", "L", "I"};
|
||||||
|
|
||||||
char buf[256];
|
outs << hex;
|
||||||
sprintf(buf, "PC = 0x%016llx", thread->readNextPC());
|
outs << "PC = " << thread->readNextPC();
|
||||||
outs << buf;
|
outs << " NPC = " << thread->readNextNPC();
|
||||||
sprintf(buf, " NPC = 0x%016llx", thread->readNextNPC());
|
|
||||||
outs << buf;
|
|
||||||
newVal = thread->readMiscReg(SparcISA::MISCREG_CCR);
|
newVal = thread->readMiscReg(SparcISA::MISCREG_CCR);
|
||||||
if(newVal != ccr)
|
if(newVal != ccr)
|
||||||
{
|
{
|
||||||
sprintf(buf, " CCR = 0x%016llx", newVal);
|
outs << " CCR = " << newVal;
|
||||||
outs << buf;
|
|
||||||
ccr = newVal;
|
ccr = newVal;
|
||||||
}
|
}
|
||||||
newVal = thread->readMiscReg(SparcISA::MISCREG_Y);
|
newVal = thread->readMiscReg(SparcISA::MISCREG_Y);
|
||||||
if(newVal != y)
|
if(newVal != y)
|
||||||
{
|
{
|
||||||
sprintf(buf, " Y = 0x%016llx", newVal);
|
outs << " Y = " << newVal;
|
||||||
outs << buf;
|
|
||||||
y = newVal;
|
y = newVal;
|
||||||
}
|
}
|
||||||
for(int y = 0; y < 4; y++)
|
for(int y = 0; y < 4; y++)
|
||||||
|
@ -102,8 +106,7 @@ Trace::InstRecord::dump(ostream &outs)
|
||||||
newVal = thread->readIntReg(index);
|
newVal = thread->readIntReg(index);
|
||||||
if(regs[index] != newVal)
|
if(regs[index] != newVal)
|
||||||
{
|
{
|
||||||
sprintf(buf, " %s%d = 0x%016llx", prefixes[y], x, newVal);
|
outs << " " << prefixes[y] << dec << x << " = " << hex << newVal;
|
||||||
outs << buf;
|
|
||||||
regs[index] = newVal;
|
regs[index] = newVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,12 +116,11 @@ Trace::InstRecord::dump(ostream &outs)
|
||||||
newVal = thread->readFloatRegBits(2 * y, 64);
|
newVal = thread->readFloatRegBits(2 * y, 64);
|
||||||
if(floats[y] != newVal)
|
if(floats[y] != newVal)
|
||||||
{
|
{
|
||||||
sprintf(buf, " F%d = 0x%016llx", 2 * y, newVal);
|
outs << " F" << dec << (2 * y) << " = " << hex << newVal;
|
||||||
outs << buf;
|
|
||||||
floats[y] = newVal;
|
floats[y] = newVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
outs << endl;
|
outs << dec << endl;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -222,6 +224,85 @@ Trace::InstRecord::dump(ostream &outs)
|
||||||
//
|
//
|
||||||
outs << endl;
|
outs << endl;
|
||||||
}
|
}
|
||||||
|
#if THE_ISA == SPARC_ISA
|
||||||
|
// Compare
|
||||||
|
if (flags[LEGION_LOCKSTEP])
|
||||||
|
{
|
||||||
|
bool compared = false;
|
||||||
|
bool diffPC = false;
|
||||||
|
bool diffInst = false;
|
||||||
|
bool diffRegs = false;
|
||||||
|
|
||||||
|
if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) {
|
||||||
|
while (!compared) {
|
||||||
|
if (shared_data->flags == OWN_M5) {
|
||||||
|
if (shared_data->pc != PC)
|
||||||
|
diffPC = true;
|
||||||
|
if (shared_data->instruction != staticInst->machInst)
|
||||||
|
diffInst = true;
|
||||||
|
for (int i = 0; i < TheISA::NumIntRegs; i++) {
|
||||||
|
if (thread->readIntReg(i) != shared_data->intregs[i])
|
||||||
|
diffRegs = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (diffPC || diffInst || diffRegs ) {
|
||||||
|
outs << "Differences found between M5 and Legion:";
|
||||||
|
if (diffPC)
|
||||||
|
outs << " [PC]";
|
||||||
|
if (diffInst)
|
||||||
|
outs << " [Instruction]";
|
||||||
|
if (diffRegs)
|
||||||
|
outs << " [IntRegs]";
|
||||||
|
outs << endl << endl;;
|
||||||
|
|
||||||
|
outs << setfill(' ') << setw(15)
|
||||||
|
<< "M5 PC: " << "0x"<< setw(16) << setfill('0')
|
||||||
|
<< hex << PC << endl;
|
||||||
|
outs << setfill(' ') << setw(15)
|
||||||
|
<< "Legion PC: " << "0x"<< setw(16) << setfill('0') << hex
|
||||||
|
<< shared_data->pc << endl << endl;
|
||||||
|
|
||||||
|
outs << setfill(' ') << setw(15)
|
||||||
|
<< "M5 Inst: " << "0x"<< setw(8)
|
||||||
|
<< setfill('0') << hex << staticInst->machInst
|
||||||
|
<< staticInst->disassemble(PC, debugSymbolTable)
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
StaticInstPtr legionInst = StaticInst::decode(makeExtMI(shared_data->instruction, thread));
|
||||||
|
outs << setfill(' ') << setw(15)
|
||||||
|
<< " Legion Inst: "
|
||||||
|
<< "0x" << setw(8) << setfill('0') << hex
|
||||||
|
<< shared_data->instruction
|
||||||
|
<< legionInst->disassemble(shared_data->pc, debugSymbolTable)
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
outs << endl;
|
||||||
|
|
||||||
|
static const char * regtypes[4] = {"%g", "%o", "%l", "%i"};
|
||||||
|
for(int y = 0; y < 4; y++)
|
||||||
|
{
|
||||||
|
for(int x = 0; x < 8; x++)
|
||||||
|
{
|
||||||
|
outs << regtypes[y] << x << " " ;
|
||||||
|
outs << "0x" << hex << setw(16) << thread->readIntReg(y*8+x);
|
||||||
|
if (thread->readIntReg(y*8 + x) != shared_data->intregs[y*8+x])
|
||||||
|
outs << " X ";
|
||||||
|
else
|
||||||
|
outs << " | ";
|
||||||
|
outs << "0x" << setw(16) << hex << shared_data->intregs[y*8+x]
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fatal("Differences found between Legion and M5\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
compared = true;
|
||||||
|
shared_data->flags = OWN_LEGION;
|
||||||
|
}
|
||||||
|
} // while
|
||||||
|
} // if not microop
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -271,6 +352,9 @@ Param<bool> exe_trace_pc_symbol(&exeTraceParams, "pc_symbol",
|
||||||
"Use symbols for the PC if available", true);
|
"Use symbols for the PC if available", true);
|
||||||
Param<bool> exe_trace_intel_format(&exeTraceParams, "intel_format",
|
Param<bool> exe_trace_intel_format(&exeTraceParams, "intel_format",
|
||||||
"print trace in intel compatible format", false);
|
"print trace in intel compatible format", false);
|
||||||
|
Param<bool> exe_trace_legion_lockstep(&exeTraceParams, "legion_lockstep",
|
||||||
|
"Compare sim state to legion state every cycle",
|
||||||
|
false);
|
||||||
Param<string> exe_trace_system(&exeTraceParams, "trace_system",
|
Param<string> exe_trace_system(&exeTraceParams, "trace_system",
|
||||||
"print trace of which system (client or server)",
|
"print trace of which system (client or server)",
|
||||||
"client");
|
"client");
|
||||||
|
@ -296,7 +380,28 @@ Trace::InstRecord::setParams()
|
||||||
flags[PRINT_REG_DELTA] = exe_trace_print_reg_delta;
|
flags[PRINT_REG_DELTA] = exe_trace_print_reg_delta;
|
||||||
flags[PC_SYMBOL] = exe_trace_pc_symbol;
|
flags[PC_SYMBOL] = exe_trace_pc_symbol;
|
||||||
flags[INTEL_FORMAT] = exe_trace_intel_format;
|
flags[INTEL_FORMAT] = exe_trace_intel_format;
|
||||||
|
flags[LEGION_LOCKSTEP] = exe_trace_legion_lockstep;
|
||||||
trace_system = exe_trace_system;
|
trace_system = exe_trace_system;
|
||||||
|
|
||||||
|
// If were going to be in lockstep with Legion
|
||||||
|
// Setup shared memory, and get otherwise ready
|
||||||
|
if (flags[LEGION_LOCKSTEP]) {
|
||||||
|
int shmfd = shmget(getuid(), sizeof(SharedData), 0777);
|
||||||
|
if (shmfd < 0)
|
||||||
|
fatal("Couldn't get shared memory fd. Is Legion running?");
|
||||||
|
|
||||||
|
shared_data = (SharedData*)shmat(shmfd, NULL, SHM_RND);
|
||||||
|
if (shared_data == (SharedData*)-1)
|
||||||
|
fatal("Couldn't allocate shared memory");
|
||||||
|
|
||||||
|
if (shared_data->flags != OWN_M5)
|
||||||
|
fatal("Shared memory has invalid owner");
|
||||||
|
|
||||||
|
if (shared_data->version != VERSION)
|
||||||
|
fatal("Shared Data is wrong version! M5: %d Legion: %d", VERSION,
|
||||||
|
shared_data->version);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -150,6 +150,7 @@ class InstRecord : public Record
|
||||||
PRINT_REG_DELTA,
|
PRINT_REG_DELTA,
|
||||||
PC_SYMBOL,
|
PC_SYMBOL,
|
||||||
INTEL_FORMAT,
|
INTEL_FORMAT,
|
||||||
|
LEGION_LOCKSTEP,
|
||||||
NUM_BITS
|
NUM_BITS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,6 @@
|
||||||
#ifndef __STD_TYPES_HH__
|
#ifndef __STD_TYPES_HH__
|
||||||
#define __STD_TYPES_HH__
|
#define __STD_TYPES_HH__
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
// inst sequence type, used to order instructions in the ready list,
|
// inst sequence type, used to order instructions in the ready list,
|
||||||
// if this rolls over the ready list order temporarily will get messed
|
// if this rolls over the ready list order temporarily will get messed
|
||||||
// up, but execution will continue and complete correctly
|
// up, but execution will continue and complete correctly
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue