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:
Kevin Lim 2006-11-10 12:44:15 -05:00
commit b5e68fb546
294 changed files with 8976 additions and 5427 deletions

View file

@ -270,6 +270,12 @@ if not conf.CheckLib(py_version_name):
print "Error: can't find Python library", py_version_name
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
# added to the LIBS environment variable.
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
env['ALL_CPU_LIST'] = ['AtomicSimpleCPU', 'TimingSimpleCPU',
'FullCPU', 'O3CPU',
'OzoneCPU']
'O3CPU', '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
# 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).
env.ExportOptions = ['FULL_SYSTEM', 'ALPHA_TLASER', 'USE_FENV', \
'USE_MYSQL', 'NO_FAST_ALLOC', 'SS_COMPATIBLE_FP', \
'USE_CHECKER', 'PYTHONHOME']
'USE_CHECKER', 'PYTHONHOME', 'TARGET_ISA']
# Define a handy 'no-op' action
def no_action(target, source, env):
@ -453,6 +461,46 @@ env.SConscript('ext/libelf/SConscript',
build_dir = os.path.join(build_root, 'libelf'),
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.
@ -560,6 +608,7 @@ for build_path in build_paths:
Help(help_text)
###################################################
#
# Let SCons do its thing. At this point SCons will use the defined

View file

@ -78,6 +78,27 @@ def makeLinuxAlphaSystem(mem_mode, mdesc = None):
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):
self = Root()
self.testsys = testSystem

View file

@ -27,12 +27,37 @@
# Authors: Lisa Hsu
from os import getcwd
from os.path import join as joinpath
import m5
from m5.objects import *
m5.AddToPath('../common')
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:
maxtick = options.maxtick
elif options.maxtime:
@ -40,7 +65,7 @@ def run(options, root, testsys):
print "simulating for: ", simtime
maxtick = simtime
else:
maxtick = -1
maxtick = m5.MaxTick
if options.checkpoint_dir:
cptdir = options.checkpoint_dir
@ -49,31 +74,55 @@ def run(options, root, testsys):
np = options.num_cpus
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:
switch_cpus = [TimingSimpleCPU(defer_registration=True, cpu_id=(np+i))
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):
switch_cpus[i].system = testsys
switch_cpus1[i].system = testsys
switch_cpus_1[i].system = testsys
if not m5.build_env['FULL_SYSTEM']:
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_cpus1[i].clock = testsys.cpu[0].clock
switch_cpus_1[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)
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_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_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)
@ -101,9 +150,9 @@ def run(options, root, testsys):
m5.panic('Checkpoint %d not found' % cpt_num)
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)
## 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.resume(testsys)
exit_event = m5.simulate(options.warmup)
m5.switchCpus(switch_cpu_list1)
if options.standard_switch:
exit_event = m5.simulate(options.warmup)
m5.switchCpus(switch_cpu_list1)
num_checkpoints = 0
exit_cause = ''
@ -135,13 +185,13 @@ def run(options, root, testsys):
exit_event = m5.simulate(when - m5.curTick())
if exit_event.getCause() == "simulate() limit reached":
m5.checkpoint(root, "/".join([cptdir,"cpt.%d"]))
m5.checkpoint(root, joinpath(cptdir, "cpt.%d"))
num_checkpoints += 1
sim_ticks = when
exit_cause = "maximum %d checkpoints dropped" % 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_cause = exit_event.getCause()
break
@ -151,24 +201,20 @@ def run(options, root, testsys):
while exit_event.getCause() == "checkpoint":
exit_event = m5.simulate(sim_ticks - m5.curTick())
if exit_event.getCause() == "simulate() limit reached":
m5.checkpoint(root, "/".join([cptdir,"cpt.%d"]))
m5.checkpoint(root, joinpath(cptdir, "cpt.%d"))
num_checkpoints += 1
else: #no checkpoints being taken via this script
exit_event = m5.simulate(maxtick)
while exit_event.getCause() == "checkpoint":
m5.checkpoint(root, "/".join([cptdir,"cpt.%d"]))
m5.checkpoint(root, joinpath(cptdir, "cpt.%d"))
num_checkpoints += 1
if num_checkpoints == max_checkpoints:
exit_cause = "maximum %d checkpoints dropped" % max_checkpoints
break
if maxtick == -1:
exit_event = m5.simulate(maxtick)
else:
exit_event = m5.simulate(maxtick - m5.curTick())
exit_event = m5.simulate(maxtick - m5.curTick())
exit_cause = exit_event.getCause()
if exit_cause == '':

View file

@ -30,6 +30,9 @@ import os, sys
from os.path import isdir, join as joinpath
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):
system()
return joinpath(disk.dir, file)
@ -60,7 +63,7 @@ def system():
if not disk.dir:
disk.dir = joinpath(system.dir, 'disks')
if not script.dir:
script.dir = joinpath(system.dir, 'boot')
script.dir = joinpath(config_root, 'boot')
system.dir = None
binary.dir = None

View file

@ -72,16 +72,8 @@ if args:
DriveCPUClass = AtomicSimpleCPU
drive_mem_mode = 'atomic'
# system under test can be any of these CPUs
if options.detailed:
TestCPUClass = DerivO3CPU
test_mem_mode = 'timing'
elif options.timing:
TestCPUClass = TimingSimpleCPU
test_mem_mode = 'timing'
else:
TestCPUClass = AtomicSimpleCPU
test_mem_mode = 'atomic'
# system under test can be any CPU
(TestCPUClass, test_mem_mode, FutureClass) = Simulation.setCPUClass(options)
TestCPUClass.clock = '2GHz'
DriveCPUClass.clock = '2GHz'
@ -103,17 +95,15 @@ test_sys = makeLinuxAlphaSystem(test_mem_mode, bm[0])
np = options.num_cpus
test_sys.cpu = [TestCPUClass(cpu_id=i) 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'),
L1Cache(size = '64kB'))
test_sys.cpu[i].connectMemPorts(test_sys.membus)
test_sys.cpu[i].mem = test_sys.physmem
if len(bm) == 2:
drive_sys = makeLinuxAlphaSystem(drive_mem_mode, bm[1])
drive_sys.cpu = DriveCPUClass(cpu_id=0)
drive_sys.cpu.connectMemPorts(drive_sys.membus)
drive_sys.cpu.mem = drive_sys.physmem
root = makeDualRoot(test_sys, drive_sys, options.etherdump)
elif len(bm) == 1:
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."
sys.exit(1)
Simulation.run(options, root, test_sys)
Simulation.run(options, root, test_sys, FutureClass)

View file

@ -41,10 +41,6 @@ from Caches import *
config_path = os.path.dirname(os.path.abspath(__file__))
config_root = os.path.dirname(config_path)
m5_root = os.path.dirname(config_root)
print m5_root
print config_path
print config_root
parser = optparse.OptionParser()
@ -92,16 +88,7 @@ if options.detailed:
process += [smt_process, ]
smt_idx += 1
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, test_mem_mode, FutureClass) = Simulation.setCPUClass(options)
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
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'),
L1Cache(size = '64kB'))
system.cpu[i].connectMemPorts(system.membus)
system.cpu[i].mem = system.physmem
system.cpu[i].workload = process
root = Root(system = system)
Simulation.run(options, root, system)
Simulation.run(options, root, system, FutureClass)

View file

@ -30,7 +30,7 @@
import os
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
# based on variable settings in the 'env' build environment.
@ -74,6 +74,7 @@ base_sources = Split('''
base/loader/aout_object.cc
base/loader/ecoff_object.cc
base/loader/elf_object.cc
base/loader/raw_object.cc
base/loader/object_file.cc
base/loader/symtab.cc
base/stats/events.cc
@ -146,45 +147,6 @@ base_sources = Split('''
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('''
cpu/trace/reader/mem_trace_reader.cc
cpu/trace/reader/ibm_reader.cc
@ -211,42 +173,9 @@ full_system_sources = Split('''
cpu/intr_control.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/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
sim/pseudo_inst.cc
@ -254,7 +183,6 @@ full_system_sources = Split('''
#dev/sinic.cc
#dev/i8254xGBe.cc
if env['TARGET_ISA'] == 'alpha':
full_system_sources += Split('''
kern/tru64/dump_mbuf.cc
@ -263,26 +191,6 @@ if env['TARGET_ISA'] == 'alpha':
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_sources = Split('''
mem/translating_port.cc
@ -296,15 +204,6 @@ syscall_emulation_sources = Split('''
# 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('''
cpu/memtest/memtest.cc
''')
@ -318,22 +217,29 @@ env.Append(CPPPATH=Dir('.'))
# Add a flag defining what THE_ISA should be for all compilation
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
# underneath 'cpu'.
if 'FullCPU' in env['CPU_MODELS']:
cpu_sources += full_cpu_sources
if env['FULL_SYSTEM']:
dev_sources = SConscript(os.path.join('dev', 'SConscript'),
exports = 'env')
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.
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']:
sources += full_system_sources
if env['ALPHA_TLASER']:
sources += turbolaser_sources
else:
sources += syscall_emulation_sources
@ -401,8 +307,15 @@ def makeEnv(label, objsfx, strip = False, **kwargs):
envList.append(newEnv)
# 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',
CCFLAGS = Split('-g3 -gdwarf-2 -O0'),
CCFLAGS = Split('%s -O0' % debug_flag),
CPPDEFINES = 'DEBUG')
# Optimized binary

View file

@ -49,10 +49,13 @@ sources = []
isa_switch_hdrs = Split('''
arguments.hh
faults.hh
interrupts.hh
isa_traits.hh
kernel_stats.hh
locked_mem.hh
process.hh
regfile.hh
remote_gdb.hh
stacktrace.hh
syscallreturn.hh
tlb.hh
@ -61,36 +64,8 @@ isa_switch_hdrs = Split('''
vtophys.hh
''')
# 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 "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)
# Set up this directory to support switching headers
env.make_switching_dir('arch', isa_switch_hdrs, env)
#################################################################
#

View file

@ -48,21 +48,29 @@ Import('env')
# Base sources used by all configurations.
base_sources = Split('''
faults.cc
isa_traits.cc
floatregfile.cc
intregfile.cc
miscregfile.cc
regfile.cc
''')
# Full-system sources
full_system_sources = Split('''
tlb.cc
arguments.cc
ev5.cc
osfpal.cc
stacktrace.cc
vtophys.cc
system.cc
freebsd/system.cc
idle_event.cc
ipr.cc
kernel_stats.cc
linux/system.cc
osfpal.cc
pagetable.cc
stacktrace.cc
remote_gdb.cc
system.cc
tlb.cc
tru64/system.cc
vtophys.cc
''')

View file

@ -35,7 +35,7 @@
using namespace AlphaISA;
AlphaArguments::Data::~Data()
Arguments::Data::~Data()
{
while (!data.empty()) {
delete [] data.front();
@ -44,7 +44,7 @@ AlphaArguments::Data::~Data()
}
char *
AlphaArguments::Data::alloc(size_t size)
Arguments::Data::alloc(size_t size)
{
char *buf = new char[size];
data.push_back(buf);
@ -52,7 +52,7 @@ AlphaArguments::Data::alloc(size_t size)
}
uint64_t
AlphaArguments::getArg(bool fp)
Arguments::getArg(bool fp)
{
if (number < 6) {
if (fp)

View file

@ -41,7 +41,7 @@ class ThreadContext;
namespace AlphaISA {
class AlphaArguments
class Arguments
{
protected:
ThreadContext *tc;
@ -65,62 +65,62 @@ class AlphaArguments
RefCountingPtr<Data> data;
public:
AlphaArguments(ThreadContext *ctx, int n = 0)
Arguments(ThreadContext *ctx, int n = 0)
: tc(ctx), number(n), data(NULL)
{ assert(number >= 0); data = new Data;}
AlphaArguments(const AlphaArguments &args)
Arguments(const Arguments &args)
: tc(args.tc), number(args.number), data(args.data) {}
~AlphaArguments() {}
~Arguments() {}
ThreadContext *getThreadContext() const { return tc; }
const AlphaArguments &operator=(const AlphaArguments &args) {
const Arguments &operator=(const Arguments &args) {
tc = args.tc;
number = args.number;
data = args.data;
return *this;
}
AlphaArguments &operator++() {
Arguments &operator++() {
++number;
assert(number >= 0);
return *this;
}
AlphaArguments operator++(int) {
AlphaArguments args = *this;
Arguments operator++(int) {
Arguments args = *this;
++number;
assert(number >= 0);
return args;
}
AlphaArguments &operator--() {
Arguments &operator--() {
--number;
assert(number >= 0);
return *this;
}
AlphaArguments operator--(int) {
AlphaArguments args = *this;
Arguments operator--(int) {
Arguments args = *this;
--number;
assert(number >= 0);
return args;
}
const AlphaArguments &operator+=(int index) {
const Arguments &operator+=(int index) {
number += index;
assert(number >= 0);
return *this;
}
const AlphaArguments &operator-=(int index) {
const Arguments &operator-=(int index) {
number -= index;
assert(number >= 0);
return *this;
}
AlphaArguments operator[](int index) {
return AlphaArguments(tc, index);
Arguments operator[](int index) {
return Arguments(tc, index);
}
template <class T>

View file

@ -31,16 +31,16 @@
#include "arch/alpha/faults.hh"
#include "arch/alpha/isa_traits.hh"
#include "arch/alpha/kernel_stats.hh"
#include "arch/alpha/osfpal.hh"
#include "arch/alpha/tlb.hh"
#include "base/kgdb.h"
#include "arch/alpha/kgdb.h"
#include "base/remote_gdb.hh"
#include "base/stats/events.hh"
#include "config/full_system.hh"
#include "cpu/base.hh"
#include "cpu/simple_thread.hh"
#include "cpu/thread_context.hh"
#include "kern/kernel_stats.hh"
#include "sim/debug.hh"
#include "sim/sim_exit.hh"
@ -60,7 +60,7 @@ AlphaISA::initCPU(ThreadContext *tc, int cpuId)
tc->setIntReg(16, 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->setNextPC(tc->readPC() + sizeof(MachInst));
@ -147,7 +147,7 @@ AlphaISA::zeroRegisters(CPU *cpu)
Fault
SimpleThread::hwrei()
{
if (!inPalMode())
if (!(readPC() & 0x3))
return new UnimplementedOpcodeFault;
setNextPC(readMiscReg(AlphaISA::IPR_EXC_ADDR));
@ -176,7 +176,7 @@ AlphaISA::MiscRegFile::getDataAsid()
}
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
@ -269,12 +269,12 @@ AlphaISA::MiscRegFile::readIpr(int idx, Fault &fault, ThreadContext *tc)
case AlphaISA::IPR_DTB_IAP:
case AlphaISA::IPR_ITB_IA:
case AlphaISA::IPR_ITB_IAP:
fault = new UnimplementedOpcodeFault;
panic("Tried to read write only register %d\n", idx);
break;
default:
// invalid IPR
fault = new UnimplementedOpcodeFault;
panic("Tried to read from invalid ipr %d\n", idx);
break;
}
@ -286,13 +286,13 @@ AlphaISA::MiscRegFile::readIpr(int idx, Fault &fault, ThreadContext *tc)
int break_ipl = -1;
#endif
Fault
void
AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc)
{
uint64_t old;
if (tc->misspeculating())
return NoFault;
return;
switch (idx) {
case AlphaISA::IPR_PALtemp0:
@ -379,10 +379,10 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc)
case AlphaISA::IPR_DTB_CM:
if (val & 0x18) {
if (tc->getKernelStats())
tc->getKernelStats()->mode(Kernel::user, tc);
tc->getKernelStats()->mode(TheISA::Kernel::user, tc);
} else {
if (tc->getKernelStats())
tc->getKernelStats()->mode(Kernel::kernel, tc);
tc->getKernelStats()->mode(TheISA::Kernel::kernel, tc);
}
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_DTB_PTE_TEMP:
// read-only registers
return new UnimplementedOpcodeFault;
panic("Tried to write read only ipr %d\n", idx);
case AlphaISA::IPR_HWINT_CLR:
case AlphaISA::IPR_SL_XMIT:
@ -547,18 +547,17 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc)
default:
// invalid IPR
return new UnimplementedOpcodeFault;
panic("Tried to write to invalid ipr %d\n", idx);
}
// no error...
return NoFault;
}
void
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));
}
}

View file

@ -125,7 +125,7 @@ void AlphaFault::invoke(ThreadContext * tc)
countStat()++;
// exception restart address
if (setRestartAddress() || !tc->inPalMode())
if (setRestartAddress() || !(tc->readPC() & 0x3))
tc->setMiscReg(AlphaISA::IPR_EXC_ADDR, tc->readPC());
if (skipFaultingInstruction()) {

View 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 &section)
{
UNSERIALIZE_ARRAY(q, NumFloatRegs);
}
}

View 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 &section);
void clear()
{ bzero(d, sizeof(d)); }
};
}
#endif

View 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();
}

View 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__

View 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 &section)
{
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

View 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 &section)
{
UNSERIALIZE_ARRAY(regs, NumIntRegs);
}
}

View 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 &section);
void clear()
{ bzero(regs, sizeof(regs)); }
};
}
#endif

140
src/arch/alpha/ipr.cc Normal file
View 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
View 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

View file

@ -629,7 +629,7 @@ decode OPCODE default Unknown::unknown() {
/* Rb is a fake dependency so here is a fun way to get
* the parser to understand that.
*/
Ra = xc->readMiscRegWithEffect(AlphaISA::IPR_CC, fault) + (Rb & 0);
Ra = xc->readMiscRegWithEffect(AlphaISA::IPR_CC) + (Rb & 0);
#else
Ra = curTick;
@ -661,12 +661,12 @@ decode OPCODE default Unknown::unknown() {
#if FULL_SYSTEM
format BasicOperate {
0xe000: rc({{
Ra = xc->readIntrFlag();
xc->setIntrFlag(0);
Ra = IntrFlag;
IntrFlag = 0;
}}, IsNonSpeculative, IsUnverifiable);
0xf000: rs({{
Ra = xc->readIntrFlag();
xc->setIntrFlag(1);
Ra = IntrFlag;
IntrFlag = 1;
}}, IsNonSpeculative, IsUnverifiable);
}
#else
@ -681,7 +681,7 @@ decode OPCODE default Unknown::unknown() {
0x00: CallPal::call_pal({{
if (!palValid ||
(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
// PAL call in non-kernel mode
fault = new UnimplementedOpcodeFault;
@ -693,7 +693,7 @@ decode OPCODE default Unknown::unknown() {
if (dopal) {
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);
@ -745,7 +745,13 @@ decode OPCODE default Unknown::unknown() {
0: OpcdecFault::hw_mfpr();
format HwMoveIPR {
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);
}
}
@ -754,7 +760,13 @@ decode OPCODE default Unknown::unknown() {
0: OpcdecFault::hw_mtpr();
format HwMoveIPR {
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); }
}}, IsIprAccess);
}
@ -783,12 +795,6 @@ decode OPCODE default Unknown::unknown() {
0x04: quiesceTime({{
R0 = AlphaPseudo::quiesceTime(xc->tcBase());
}}, IsNonSpeculative, IsUnverifiable);
0x10: ivlb({{
AlphaPseudo::ivlb(xc->tcBase());
}}, No_OpClass, IsNonSpeculative);
0x11: ivle({{
AlphaPseudo::ivle(xc->tcBase());
}}, No_OpClass, IsNonSpeculative);
0x20: m5exit_old({{
AlphaPseudo::m5exit_old(xc->tcBase());
}}, No_OpClass, IsNonSpeculative);

View file

@ -46,7 +46,7 @@ output exec {{
inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
{
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;
}
return fault;
@ -229,7 +229,7 @@ def template FloatingPointExecute {{
%(code)s;
} else {
fesetround(getC99RoundingMode(
xc->readMiscReg(AlphaISA::Fpcr_DepTag)));
xc->readMiscReg(AlphaISA::MISCREG_FPCR)));
%(code)s;
fesetround(FE_TONEAREST);
}

View file

@ -71,6 +71,7 @@ output exec {{
#if FULL_SYSTEM
#include "sim/pseudo_inst.hh"
#endif
#include "arch/alpha/ipr.hh"
#include "base/fenv.hh"
#include "config/ss_compatible_fp.hh"
#include "cpu/base.hh"
@ -183,8 +184,9 @@ def operands {{
'Fc': ('FloatReg', 'df', 'FC', 'IsFloating', 3),
'Mem': ('Mem', 'uq', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4),
'NPC': ('NPC', 'uq', None, ( None, None, 'IsControl' ), 4),
'Runiq': ('ControlReg', 'uq', 'TheISA::Uniq_DepTag', None, 1),
'FPCR': (' ControlReg', 'uq', 'TheISA::Fpcr_DepTag', None, 1),
'Runiq': ('ControlReg', 'uq', 'MISCREG_UNIQ', 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
'R0': ('IntReg', 'uq', '0', None, 1),
'R16': ('IntReg', 'uq', '16', None, 1),
@ -214,11 +216,6 @@ output header {{
/// live here and not in the AlphaISA namespace.
enum DependenceTags {
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.

View file

@ -34,6 +34,7 @@
namespace LittleEndianGuest {}
#include "arch/alpha/ipr.hh"
#include "arch/alpha/types.hh"
#include "config/full_system.hh"
#include "sim/host.hh"
@ -49,12 +50,7 @@ namespace AlphaISA
// 0..31 are the integer regs 0..31
// 32..63 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag)
FP_Base_DepTag = 40,
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
Ctrl_Base_DepTag = 72
};
StaticInstPtr decodeInst(ExtMachInst);
@ -118,7 +114,6 @@ namespace AlphaISA
NumInterruptLevels = INTLEVEL_EXTERNAL_MAX
};
// EV5 modes
enum mode_type
{
@ -131,100 +126,6 @@ namespace AlphaISA
#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
const int NumIntArchRegs = 32;
@ -279,9 +180,6 @@ namespace AlphaISA
// Alpha UNOP (ldq_u r31,0(r0))
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__

View 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 &section)
{
::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 */

View 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 &section);
};
} /* end namespace AlphaISA::Kernel */
} /* end namespace AlphaISA */
#endif // __ARCH_ALPHA_KERNEL_STATS_HH__

View file

@ -160,15 +160,4 @@
/* Too much? Must be large enough for register transfer. */
#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__ */

View file

@ -42,6 +42,7 @@
#include "arch/arguments.hh"
#include "arch/vtophys.hh"
#include "arch/alpha/idle_event.hh"
#include "arch/alpha/linux/system.hh"
#include "arch/alpha/linux/threadinfo.hh"
#include "arch/alpha/system.hh"

View file

@ -38,6 +38,7 @@ class ThreadContext;
class BreakPCEvent;
class IdleStartEvent;
#include "arch/alpha/idle_event.hh"
#include "arch/alpha/system.hh"
#include "kern/linux/events.hh"

View file

@ -37,7 +37,7 @@
* ISA-specific helper functions for locked memory accesses.
*/
#include "arch/isa_traits.hh"
#include "arch/alpha/miscregfile.hh"
#include "base/misc.hh"
#include "mem/request.hh"
@ -48,8 +48,8 @@ template <class XC>
inline void
handleLockedRead(XC *xc, Request *req)
{
xc->setMiscReg(Lock_Addr_DepTag, req->getPaddr() & ~0xf);
xc->setMiscReg(Lock_Flag_DepTag, true);
xc->setMiscReg(MISCREG_LOCKADDR, req->getPaddr() & ~0xf);
xc->setMiscReg(MISCREG_LOCKFLAG, true);
}
@ -63,13 +63,13 @@ handleLockedWrite(XC *xc, Request *req)
req->setScResult(2);
} else {
// standard store conditional
bool lock_flag = xc->readMiscReg(Lock_Flag_DepTag);
Addr lock_addr = xc->readMiscReg(Lock_Addr_DepTag);
bool lock_flag = xc->readMiscReg(MISCREG_LOCKFLAG);
Addr lock_addr = xc->readMiscReg(MISCREG_LOCKADDR);
if (!lock_flag || (req->getPaddr() & ~0xf) != lock_addr) {
// Lock flag not set or addr mismatch in CPU;
// don't even bother sending to memory system
req->setScResult(0);
xc->setMiscReg(Lock_Flag_DepTag, false);
xc->setMiscReg(MISCREG_LOCKFLAG, false);
// the rest of this code is not architectural;
// it's just a debugging aid to help detect
// livelock by warning on long sequences of failed

View 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 &section)
{
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
}
}

View 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 &section);
#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

View 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 &section)
{
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
View 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 &section)
{
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
}
}

View file

@ -31,8 +31,11 @@
#ifndef __ARCH_ALPHA_REGFILE_HH__
#define __ARCH_ALPHA_REGFILE_HH__
#include "arch/alpha/types.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 <string>
@ -45,111 +48,6 @@ class ThreadContext;
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 &section);
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 &section);
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 &section);
#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 {
protected:
@ -215,22 +113,20 @@ namespace AlphaISA
return miscRegFile.readReg(miscReg);
}
MiscReg readMiscRegWithEffect(int miscReg,
Fault &fault, ThreadContext *tc)
MiscReg readMiscRegWithEffect(int miscReg, ThreadContext *tc)
{
fault = NoFault;
return miscRegFile.readRegWithEffect(miscReg, fault, tc);
return miscRegFile.readRegWithEffect(miscReg, 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)
{
return miscRegFile.setRegWithEffect(miscReg, val, tc);
miscRegFile.setRegWithEffect(miscReg, val, tc);
}
FloatReg readFloatReg(int floatReg)
@ -253,26 +149,24 @@ namespace AlphaISA
return readFloatRegBits(floatReg);
}
Fault setFloatReg(int floatReg, const FloatReg &val)
void setFloatReg(int floatReg, const 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;
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)
@ -280,9 +174,9 @@ namespace AlphaISA
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);
@ -298,10 +192,6 @@ namespace AlphaISA
void copyRegs(ThreadContext *src, ThreadContext *dest);
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
#if FULL_SYSTEM
void copyIprs(ThreadContext *src, ThreadContext *dest);
#endif
} // namespace AlphaISA
#endif

View 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;
}
}

View 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__ */

View file

@ -40,329 +40,331 @@
#include "sim/system.hh"
using namespace std;
using namespace AlphaISA;
ProcessInfo::ProcessInfo(ThreadContext *_tc)
: tc(_tc)
namespace AlphaISA
{
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))
panic("thread info not compiled into kernel\n");
thread_info_size = vp->readGtoH<int32_t>(addr);
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("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("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_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);
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)
{
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;
tc->delVirtPort(vp);
}
if (!kernel) {
stack.push_back(console);
return;
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;
}
SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
Addr ksp = tc->readIntReg(TheISA::StackPointerReg);
Addr bottom = ksp & ~0x3fff;
Addr addr;
int
ProcessInfo::pid(Addr ksp) const
{
Addr task = this->task(ksp);
if (!task)
return -1;
if (is_call) {
if (!symtab->findNearestAddr(pc, addr))
panic("could not find address %#x", pc);
uint16_t pd;
stack.push_back(addr);
pc = tc->readPC();
VirtualPort *vp;
vp = tc->getVirtPort();
pd = vp->readGtoH<uint16_t>(task + pid_off);
tc->delVirtPort(vp);
return pd;
}
Addr ra;
int size;
string
ProcessInfo::name(Addr ksp) const
{
Addr task = this->task(ksp);
if (!task)
return "console";
while (ksp > bottom) {
if (!symtab->findNearestAddr(pc, addr))
panic("could not find symbol for pc=%#x", pc);
assert(pc >= addr && "symbol botch: callpc < func");
char comm[256];
CopyStringOut(tc, comm, task + name_off, sizeof(comm));
if (!comm[0])
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;
}
if (decodePrologue(ksp, pc, addr, size, ra)) {
if (!ra)
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 (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);
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");
}
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");
}
panic("unwinding too far");
}
bool
StackTrace::isEntry(Addr addr)
{
if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp12))
return true;
bool
StackTrace::isEntry(Addr addr)
{
if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp12))
return true;
if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp7))
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_PALtemp11))
return true;
if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp21))
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_PALtemp9))
return true;
if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp2))
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 &reg, 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;
}
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;
/*
* 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;
// 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;
for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) {
MachInst inst;
CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst));
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;
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;
}
bool
StackTrace::decodeSave(MachInst inst, int &reg, 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;
}
return true;
}
#if TRACING_ON
void
StackTrace::dump()
{
StringWrap name(tc->getCpuPtr()->name());
SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
void
StackTrace::dump()
{
StringWrap name(tc->getCpuPtr()->name());
SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
DPRINTFN("------ Stack ------\n");
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);
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);
DPRINTFN("%#x: %s\n", addr, symbol);
}
}
}
#endif
}

View file

@ -35,87 +35,91 @@
#include "cpu/static_inst.hh"
class ThreadContext;
class StackTrace;
class ProcessInfo
namespace AlphaISA
{
private:
ThreadContext *tc;
class StackTrace;
int thread_info_size;
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 &reg, 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()
class ProcessInfo
{
tc = 0;
stack.clear();
}
private:
ThreadContext *tc;
bool valid() const { return tc != NULL; }
bool trace(ThreadContext *tc, StaticInstPtr inst);
int thread_info_size;
int task_struct_size;
int task_off;
int pid_off;
int name_off;
public:
const std::vector<Addr> &getstack() const { return stack; }
public:
ProcessInfo(ThreadContext *_tc);
static const int user = 1;
static const int console = 2;
static const int unknown = 3;
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 &reg, 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
private:
void dump();
private:
void dump();
public:
void dprintf() { if (DTRACE(Stack)) dump(); }
public:
void dprintf() { if (DTRACE(Stack)) dump(); }
#else
public:
void dprintf() {}
public:
void dprintf() {}
#endif
};
};
inline bool
StackTrace::trace(ThreadContext *tc, StaticInstPtr inst)
{
if (!inst->isCall() && !inst->isReturn())
return false;
inline bool
StackTrace::trace(ThreadContext *tc, StaticInstPtr inst)
{
if (!inst->isCall() && !inst->isReturn())
return false;
if (valid())
clear();
if (valid())
clear();
trace(tc, !inst->isReturn());
return true;
trace(tc, !inst->isReturn());
return true;
}
}
#endif // __ARCH_ALPHA_STACKTRACE_HH__

View file

@ -29,10 +29,12 @@
* Nathan Binkert
*/
#include <sys/signal.h>
#include "arch/alpha/ev5.hh"
#include "arch/alpha/system.hh"
#include "arch/alpha/remote_gdb.hh"
#include "arch/vtophys.hh"
#include "base/remote_gdb.hh"
#include "base/loader/object_file.hh"
#include "base/loader/symtab.hh"
#include "base/trace.hh"
@ -196,7 +198,7 @@ AlphaSystem::setAlphaAccess(Addr access)
bool
AlphaSystem::breakpoint()
{
return remoteGDB[0]->trap(ALPHA_KENTRY_INT);
return remoteGDB[0]->trap(SIGTRAP);
}
void

File diff suppressed because it is too large Load diff

View file

@ -36,6 +36,7 @@
#include "arch/alpha/ev5.hh"
#include "arch/alpha/isa_traits.hh"
#include "arch/alpha/pagetable.hh"
#include "arch/alpha/utility.hh"
#include "arch/alpha/vtophys.hh"
#include "base/statistics.hh"
@ -45,82 +46,87 @@
class ThreadContext;
class AlphaTLB : public SimObject
namespace AlphaISA
{
protected:
typedef std::multimap<Addr, int> PageTable;
PageTable lookupTable; // Quick lookup into page table
class PTE;
AlphaISA::PTE *table; // the Page Table
int size; // TLB Size
int nlu; // not last used entry (for replacement)
class TLB : public SimObject
{
protected:
typedef std::multimap<Addr, int> PageTable;
PageTable lookupTable; // Quick lookup into page table
void nextnlu() { if (++nlu >= size) nlu = 0; }
AlphaISA::PTE *lookup(Addr vpn, uint8_t asn) const;
PTE *table; // the Page Table
int size; // TLB Size
int nlu; // not last used entry (for replacement)
public:
AlphaTLB(const std::string &name, int size);
virtual ~AlphaTLB();
void nextnlu() { if (++nlu >= size) nlu = 0; }
PTE *lookup(Addr vpn, uint8_t asn) const;
int getsize() const { return size; }
public:
TLB(const std::string &name, int size);
virtual ~TLB();
AlphaISA::PTE &index(bool advance = true);
void insert(Addr vaddr, AlphaISA::PTE &pte);
int getsize() const { return size; }
void flushAll();
void flushProcesses();
void flushAddr(Addr addr, uint8_t asn);
PTE &index(bool advance = true);
void insert(Addr vaddr, PTE &pte);
// 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);
}
void flushAll();
void flushProcesses();
void flushAddr(Addr addr, uint8_t asn);
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
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
};
static Fault checkCacheability(RequestPtr &req);
class AlphaITB : public AlphaTLB
{
protected:
mutable Stats::Scalar<> hits;
mutable Stats::Scalar<> misses;
mutable Stats::Scalar<> acv;
mutable Stats::Formula accesses;
// Checkpointing
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
};
public:
AlphaITB(const std::string &name, int size);
virtual void regStats();
class ITB : public TLB
{
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
{
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) const;
};
public:
AlphaDTB(const std::string &name, int size);
virtual void regStats();
class DTB : public TLB
{
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__

View file

@ -42,12 +42,18 @@
namespace AlphaISA
{
static inline bool
inUserMode(ThreadContext *tc)
{
return (tc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0;
}
static inline ExtMachInst
makeExtMI(MachInst inst, ThreadContext * xc) {
makeExtMI(MachInst inst, Addr pc) {
#if FULL_SYSTEM
ExtMachInst ext_inst = inst;
if (xc->readPC() && 0x1)
return ext_inst|=(static_cast<ExtMachInst>(xc->readPC() & 0x1) << 32);
if (pc && 0x1)
return ext_inst|=(static_cast<ExtMachInst>(pc & 0x1) << 32);
else
return ext_inst;
#else

View file

@ -220,20 +220,20 @@ namespace MipsISA
return miscRegFile[misc_reg];
}
MiscReg readRegWithEffect(int misc_reg, Fault &fault, ThreadContext *tc)
MiscReg readRegWithEffect(int misc_reg, ThreadContext *tc)
{
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)
{
miscRegFile[misc_reg] = val; return NoFault;
miscRegFile[misc_reg] = val;
}
friend class RegFile;

View file

@ -62,22 +62,20 @@ namespace MipsISA
return miscRegFile.readReg(miscReg);
}
MiscReg readMiscRegWithEffect(int miscReg,
Fault &fault, ThreadContext *tc)
MiscReg readMiscRegWithEffect(int miscReg, ThreadContext *tc)
{
fault = NoFault;
return miscRegFile.readRegWithEffect(miscReg, fault, tc);
return miscRegFile.readRegWithEffect(miscReg, 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)
{
return miscRegFile.setRegWithEffect(miscReg, val, tc);
miscRegFile.setRegWithEffect(miscReg, val, tc);
}
FloatRegVal readFloatReg(int floatReg)
@ -100,24 +98,24 @@ namespace MipsISA
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)
@ -125,9 +123,9 @@ namespace MipsISA
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:

View file

@ -37,6 +37,9 @@
class ThreadContext;
class StackTrace;
namespace MipsISA
{
class ProcessInfo
{
private:
@ -118,4 +121,6 @@ StackTrace::trace(ThreadContext *tc, StaticInstPtr inst)
return true;
}
}
#endif // __ARCH_MIPS_STACKTRACE_HH__

View file

@ -54,7 +54,11 @@ base_sources = Split('''
# Full-system sources
full_system_sources = Split('''
ua2005.cc
arguments.cc
remote_gdb.cc
stacktrace.cc
system.cc
tlb.cc
vtophys.cc
''')

View 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
View 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__

View file

@ -219,4 +219,4 @@ namespace SparcISA
};
#endif // __ARCH_SPARC_TLB_HH__
#endif // __ARCH_SPARC_ASI_HH__

View file

@ -33,12 +33,14 @@
#include "arch/sparc/faults.hh"
#include "arch/sparc/isa_traits.hh"
#include "arch/sparc/process.hh"
#include "arch/sparc/types.hh"
#include "base/bitfield.hh"
#include "base/trace.hh"
#include "config/full_system.hh"
#include "cpu/base.hh"
#include "cpu/thread_context.hh"
#if !FULL_SYSTEM
#include "arch/sparc/process.hh"
#include "mem/page_table.hh"
#include "sim/process.hh"
#endif
@ -48,214 +50,352 @@ using namespace std;
namespace SparcISA
{
FaultName InternalProcessorError::_name = "intprocerr";
TrapType InternalProcessorError::_trapType = 0x029;
FaultPriority InternalProcessorError::_priority = 4;
FaultStat InternalProcessorError::_count;
template<> SparcFaultBase::FaultVals
SparcFault<PowerOnReset>::vals =
{"power_on_reset", 0x001, 0, {H, H, H}};
FaultName MemAddressNotAligned::_name = "unalign";
TrapType MemAddressNotAligned::_trapType = 0x034;
FaultPriority MemAddressNotAligned::_priority = 10;
FaultStat MemAddressNotAligned::_count;
template<> SparcFaultBase::FaultVals
SparcFault<WatchDogReset>::vals =
{"watch_dog_reset", 0x002, 120, {H, H, H}};
FaultName PowerOnReset::_name = "pow_reset";
TrapType PowerOnReset::_trapType = 0x001;
FaultPriority PowerOnReset::_priority = 0;
FaultStat PowerOnReset::_count;
template<> SparcFaultBase::FaultVals
SparcFault<ExternallyInitiatedReset>::vals =
{"externally_initiated_reset", 0x003, 110, {H, H, H}};
FaultName WatchDogReset::_name = "watch_dog_reset";
TrapType WatchDogReset::_trapType = 0x002;
FaultPriority WatchDogReset::_priority = 1;
FaultStat WatchDogReset::_count;
template<> SparcFaultBase::FaultVals
SparcFault<SoftwareInitiatedReset>::vals =
{"software_initiated_reset", 0x004, 130, {SH, SH, H}};
FaultName ExternallyInitiatedReset::_name = "extern_reset";
TrapType ExternallyInitiatedReset::_trapType = 0x003;
FaultPriority ExternallyInitiatedReset::_priority = 1;
FaultStat ExternallyInitiatedReset::_count;
template<> SparcFaultBase::FaultVals
SparcFault<REDStateException>::vals =
{"RED_state_exception", 0x005, 1, {H, H, H}};
FaultName SoftwareInitiatedReset::_name = "software_reset";
TrapType SoftwareInitiatedReset::_trapType = 0x004;
FaultPriority SoftwareInitiatedReset::_priority = 1;
FaultStat SoftwareInitiatedReset::_count;
template<> SparcFaultBase::FaultVals
SparcFault<StoreError>::vals =
{"store_error", 0x007, 201, {H, H, H}};
FaultName REDStateException::_name = "red_counte";
TrapType REDStateException::_trapType = 0x005;
FaultPriority REDStateException::_priority = 1;
FaultStat REDStateException::_count;
template<> SparcFaultBase::FaultVals
SparcFault<InstructionAccessException>::vals =
{"instruction_access_exception", 0x008, 300, {H, H, H}};
FaultName InstructionAccessException::_name = "inst_access";
TrapType InstructionAccessException::_trapType = 0x008;
FaultPriority InstructionAccessException::_priority = 5;
FaultStat InstructionAccessException::_count;
//XXX This trap is apparently dropped from ua2005
/*template<> SparcFaultBase::FaultVals
SparcFault<InstructionAccessMMUMiss>::vals =
{"inst_mmu", 0x009, 2, {H, H, H}};*/
FaultName InstructionAccessMMUMiss::_name = "inst_mmu";
TrapType InstructionAccessMMUMiss::_trapType = 0x009;
FaultPriority InstructionAccessMMUMiss::_priority = 2;
FaultStat InstructionAccessMMUMiss::_count;
template<> SparcFaultBase::FaultVals
SparcFault<InstructionAccessError>::vals =
{"instruction_access_error", 0x00A, 400, {H, H, H}};
FaultName InstructionAccessError::_name = "inst_error";
TrapType InstructionAccessError::_trapType = 0x00A;
FaultPriority InstructionAccessError::_priority = 3;
FaultStat InstructionAccessError::_count;
template<> SparcFaultBase::FaultVals
SparcFault<IllegalInstruction>::vals =
{"illegal_instruction", 0x010, 620, {H, H, H}};
FaultName IllegalInstruction::_name = "illegal_inst";
TrapType IllegalInstruction::_trapType = 0x010;
FaultPriority IllegalInstruction::_priority = 7;
FaultStat IllegalInstruction::_count;
template<> SparcFaultBase::FaultVals
SparcFault<PrivilegedOpcode>::vals =
{"privileged_opcode", 0x011, 700, {P, SH, SH}};
FaultName PrivilegedOpcode::_name = "priv_opcode";
TrapType PrivilegedOpcode::_trapType = 0x011;
FaultPriority PrivilegedOpcode::_priority = 6;
FaultStat PrivilegedOpcode::_count;
//XXX This trap is apparently dropped from ua2005
/*template<> SparcFaultBase::FaultVals
SparcFault<UnimplementedLDD>::vals =
{"unimp_ldd", 0x012, 6, {H, H, H}};*/
FaultName UnimplementedLDD::_name = "unimp_ldd";
TrapType UnimplementedLDD::_trapType = 0x012;
FaultPriority UnimplementedLDD::_priority = 6;
FaultStat UnimplementedLDD::_count;
//XXX This trap is apparently dropped from ua2005
/*template<> SparcFaultBase::FaultVals
SparcFault<UnimplementedSTD>::vals =
{"unimp_std", 0x013, 6, {H, H, H}};*/
FaultName UnimplementedSTD::_name = "unimp_std";
TrapType UnimplementedSTD::_trapType = 0x013;
FaultPriority UnimplementedSTD::_priority = 6;
FaultStat UnimplementedSTD::_count;
template<> SparcFaultBase::FaultVals
SparcFault<FpDisabled>::vals =
{"fp_disabled", 0x020, 800, {P, P, H}};
FaultName FpDisabled::_name = "fp_disabled";
TrapType FpDisabled::_trapType = 0x020;
FaultPriority FpDisabled::_priority = 8;
FaultStat FpDisabled::_count;
template<> SparcFaultBase::FaultVals
SparcFault<FpExceptionIEEE754>::vals =
{"fp_exception_ieee_754", 0x021, 1110, {P, P, H}};
FaultName FpExceptionIEEE754::_name = "fp_754";
TrapType FpExceptionIEEE754::_trapType = 0x021;
FaultPriority FpExceptionIEEE754::_priority = 11;
FaultStat FpExceptionIEEE754::_count;
template<> SparcFaultBase::FaultVals
SparcFault<FpExceptionOther>::vals =
{"fp_exception_other", 0x022, 1110, {P, P, H}};
FaultName FpExceptionOther::_name = "fp_other";
TrapType FpExceptionOther::_trapType = 0x022;
FaultPriority FpExceptionOther::_priority = 11;
FaultStat FpExceptionOther::_count;
template<> SparcFaultBase::FaultVals
SparcFault<TagOverflow>::vals =
{"tag_overflow", 0x023, 1400, {P, P, H}};
FaultName TagOverflow::_name = "tag_overflow";
TrapType TagOverflow::_trapType = 0x023;
FaultPriority TagOverflow::_priority = 14;
FaultStat TagOverflow::_count;
template<> SparcFaultBase::FaultVals
SparcFault<CleanWindow>::vals =
{"clean_window", 0x024, 1010, {P, P, H}};
FaultName DivisionByZero::_name = "div_by_zero";
TrapType DivisionByZero::_trapType = 0x028;
FaultPriority DivisionByZero::_priority = 15;
FaultStat DivisionByZero::_count;
template<> SparcFaultBase::FaultVals
SparcFault<DivisionByZero>::vals =
{"division_by_zero", 0x028, 1500, {P, P, H}};
FaultName DataAccessException::_name = "data_access";
TrapType DataAccessException::_trapType = 0x030;
FaultPriority DataAccessException::_priority = 12;
FaultStat DataAccessException::_count;
template<> SparcFaultBase::FaultVals
SparcFault<InternalProcessorError>::vals =
{"internal_processor_error", 0x029, 4, {H, H, H}};
FaultName DataAccessMMUMiss::_name = "data_mmu";
TrapType DataAccessMMUMiss::_trapType = 0x031;
FaultPriority DataAccessMMUMiss::_priority = 12;
FaultStat DataAccessMMUMiss::_count;
template<> SparcFaultBase::FaultVals
SparcFault<InstructionInvalidTSBEntry>::vals =
{"instruction_invalid_tsb_entry", 0x02A, 210, {H, H, SH}};
FaultName DataAccessError::_name = "data_error";
TrapType DataAccessError::_trapType = 0x032;
FaultPriority DataAccessError::_priority = 12;
FaultStat DataAccessError::_count;
template<> SparcFaultBase::FaultVals
SparcFault<DataInvalidTSBEntry>::vals =
{"data_invalid_tsb_entry", 0x02B, 1203, {H, H, H}};
FaultName DataAccessProtection::_name = "data_protection";
TrapType DataAccessProtection::_trapType = 0x033;
FaultPriority DataAccessProtection::_priority = 12;
FaultStat DataAccessProtection::_count;
template<> SparcFaultBase::FaultVals
SparcFault<DataAccessException>::vals =
{"data_access_exception", 0x030, 1201, {H, H, H}};
FaultName LDDFMemAddressNotAligned::_name = "unalign_lddf";
TrapType LDDFMemAddressNotAligned::_trapType = 0x035;
FaultPriority LDDFMemAddressNotAligned::_priority = 10;
FaultStat LDDFMemAddressNotAligned::_count;
//XXX This trap is apparently dropped from ua2005
/*template<> SparcFaultBase::FaultVals
SparcFault<DataAccessMMUMiss>::vals =
{"data_mmu", 0x031, 12, {H, H, H}};*/
FaultName STDFMemAddressNotAligned::_name = "unalign_stdf";
TrapType STDFMemAddressNotAligned::_trapType = 0x036;
FaultPriority STDFMemAddressNotAligned::_priority = 10;
FaultStat STDFMemAddressNotAligned::_count;
template<> SparcFaultBase::FaultVals
SparcFault<DataAccessError>::vals =
{"data_access_error", 0x032, 1210, {H, H, H}};
FaultName PrivilegedAction::_name = "priv_action";
TrapType PrivilegedAction::_trapType = 0x037;
FaultPriority PrivilegedAction::_priority = 11;
FaultStat PrivilegedAction::_count;
template<> SparcFaultBase::FaultVals
SparcFault<DataAccessProtection>::vals =
{"data_access_protection", 0x033, 1207, {H, H, H}};
FaultName LDQFMemAddressNotAligned::_name = "unalign_ldqf";
TrapType LDQFMemAddressNotAligned::_trapType = 0x038;
FaultPriority LDQFMemAddressNotAligned::_priority = 10;
FaultStat LDQFMemAddressNotAligned::_count;
template<> SparcFaultBase::FaultVals
SparcFault<MemAddressNotAligned>::vals =
{"mem_address_not_aligned", 0x034, 1020, {H, H, H}};
FaultName STQFMemAddressNotAligned::_name = "unalign_stqf";
TrapType STQFMemAddressNotAligned::_trapType = 0x039;
FaultPriority STQFMemAddressNotAligned::_priority = 10;
FaultStat STQFMemAddressNotAligned::_count;
template<> SparcFaultBase::FaultVals
SparcFault<LDDFMemAddressNotAligned>::vals =
{"LDDF_mem_address_not_aligned", 0x035, 1010, {H, H, H}};
FaultName AsyncDataError::_name = "async_data";
TrapType AsyncDataError::_trapType = 0x040;
FaultPriority AsyncDataError::_priority = 2;
FaultStat AsyncDataError::_count;
template<> SparcFaultBase::FaultVals
SparcFault<STDFMemAddressNotAligned>::vals =
{"STDF_mem_address_not_aligned", 0x036, 1010, {H, H, H}};
FaultName CleanWindow::_name = "clean_win";
TrapType CleanWindow::_trapType = 0x024;
FaultPriority CleanWindow::_priority = 10;
FaultStat CleanWindow::_count;
template<> SparcFaultBase::FaultVals
SparcFault<PrivilegedAction>::vals =
{"privileged_action", 0x037, 1110, {H, H, SH}};
//The enumerated faults
template<> SparcFaultBase::FaultVals
SparcFault<LDQFMemAddressNotAligned>::vals =
{"LDQF_mem_address_not_aligned", 0x038, 1010, {H, H, H}};
FaultName InterruptLevelN::_name = "interrupt_n";
TrapType InterruptLevelN::_baseTrapType = 0x041;
FaultStat InterruptLevelN::_count;
template<> SparcFaultBase::FaultVals
SparcFault<STQFMemAddressNotAligned>::vals =
{"STQF_mem_address_not_aligned", 0x039, 1010, {H, H, H}};
FaultName SpillNNormal::_name = "spill_n_normal";
TrapType SpillNNormal::_baseTrapType = 0x080;
FaultPriority SpillNNormal::_priority = 9;
FaultStat SpillNNormal::_count;
template<> SparcFaultBase::FaultVals
SparcFault<InstructionRealTranslationMiss>::vals =
{"instruction_real_translation_miss", 0x03E, 208, {H, H, SH}};
FaultName SpillNOther::_name = "spill_n_other";
TrapType SpillNOther::_baseTrapType = 0x0A0;
FaultPriority SpillNOther::_priority = 9;
FaultStat SpillNOther::_count;
template<> SparcFaultBase::FaultVals
SparcFault<DataRealTranslationMiss>::vals =
{"data_real_translation_miss", 0x03F, 1203, {H, H, H}};
FaultName FillNNormal::_name = "fill_n_normal";
TrapType FillNNormal::_baseTrapType = 0x0C0;
FaultPriority FillNNormal::_priority = 9;
FaultStat FillNNormal::_count;
//XXX This trap is apparently dropped from ua2005
/*template<> SparcFaultBase::FaultVals
SparcFault<AsyncDataError>::vals =
{"async_data", 0x040, 2, {H, H, H}};*/
FaultName FillNOther::_name = "fill_n_other";
TrapType FillNOther::_baseTrapType = 0x0E0;
FaultPriority FillNOther::_priority = 9;
FaultStat FillNOther::_count;
template<> SparcFaultBase::FaultVals
SparcFault<InterruptLevelN>::vals =
{"interrupt_level_n", 0x041, 0, {P, P, SH}};
FaultName TrapInstruction::_name = "trap_inst_n";
TrapType TrapInstruction::_baseTrapType = 0x100;
FaultPriority TrapInstruction::_priority = 16;
FaultStat TrapInstruction::_count;
template<> SparcFaultBase::FaultVals
SparcFault<HstickMatch>::vals =
{"hstick_match", 0x05E, 1601, {H, H, H}};
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
FaultName PageTableFault::_name = "page_table_fault";
TrapType PageTableFault::_trapType = 0x0000;
FaultPriority PageTableFault::_priority = 0;
FaultStat PageTableFault::_count;
template<> SparcFaultBase::FaultVals
SparcFault<PageTableFault>::vals =
{"page_table_fault", 0x0000, 0, {SH, SH, SH}};
#endif
/**
* This sets everything up for a normal trap except for actually jumping to
* the handler. It will need to be expanded to include the state machine in
* the manual. Right now it assumes that traps will always be to the
* privileged level.
* This causes the thread context to enter RED state. This causes the side
* effects which go with entering RED state because of a trap.
*/
void doNormalFault(ThreadContext *tc, TrapType tt)
void enterREDState(ThreadContext *tc)
{
uint64_t TL = tc->readMiscReg(MISCREG_TL);
uint64_t TSTATE = tc->readMiscReg(MISCREG_TSTATE);
uint64_t PSTATE = tc->readMiscReg(MISCREG_PSTATE);
uint64_t HPSTATE = tc->readMiscReg(MISCREG_HPSTATE);
uint64_t CCR = tc->readMiscReg(MISCREG_CCR);
uint64_t ASI = tc->readMiscReg(MISCREG_ASI);
uint64_t CWP = tc->readMiscReg(MISCREG_CWP);
uint64_t CANSAVE = tc->readMiscReg(MISCREG_CANSAVE);
uint64_t GL = tc->readMiscReg(MISCREG_GL);
uint64_t PC = tc->readPC();
uint64_t NPC = tc->readNextPC();
//@todo Disable the mmu?
//@todo Disable watchpoints?
MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE);
//HPSTATE.red = 1
HPSTATE |= (1 << 5);
//HPSTATE.hpriv = 1
HPSTATE |= (1 << 2);
tc->setMiscReg(MISCREG_HPSTATE, HPSTATE);
}
/**
* 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
TL++;
@ -289,10 +429,10 @@ void doNormalFault(ThreadContext *tc, TrapType tt)
tc->setMiscReg(MISCREG_TT, tt);
//Update the global register level
if(1/*We're delivering the trap in priveleged mode*/)
tc->setMiscReg(MISCREG_GL, max<int>(GL+1, MaxGL));
if(!gotoHpriv)
tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxPGL));
else
tc->setMiscReg(MISCREG_GL, max<int>(GL+1, MaxPGL));
tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL));
//PSTATE.mm is unchanged
//PSTATE.pef = whether or not an fpu is present
@ -301,7 +441,7 @@ void doNormalFault(ThreadContext *tc, TrapType tt)
PSTATE |= (1 << 4);
//PSTATE.am = 0
PSTATE &= ~(1 << 3);
if(1/*We're delivering the trap in priveleged mode*/)
if(!gotoHpriv)
{
//PSTATE.priv = 1
PSTATE |= (1 << 2);
@ -322,7 +462,7 @@ void doNormalFault(ThreadContext *tc, TrapType tt)
//XXX Where exactly is this field?
tc->setMiscReg(MISCREG_PSTATE, PSTATE);
if(0/*We're delivering the trap in hyperprivileged mode*/)
if(gotoHpriv)
{
//HPSTATE.red = 0
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
void SparcFault::invoke(ThreadContext * tc)
void SparcFaultBase::invoke(ThreadContext * tc)
{
FaultBase::invoke(tc);
countStat()++;
//Use the SPARC trap state machine
/*// exception restart address
if (setRestartAddress() || !tc->inPalMode())
tc->setMiscReg(AlphaISA::IPR_EXC_ADDR, tc->regs.pc);
//We can refer to this to see what the trap level -was-, but something
//in the middle could change it in the regfile out from under us.
MiscReg TL = tc->readMiscReg(MISCREG_TL);
MiscReg TT = tc->readMiscReg(MISCREG_TT);
MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE);
MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE);
if (skipFaultingInstruction()) {
// traps... skip faulting instruction.
tc->setMiscReg(AlphaISA::IPR_EXC_ADDR,
tc->readMiscReg(AlphaISA::IPR_EXC_ADDR) + 4);
Addr PC, NPC;
PrivilegeLevel current;
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())
AlphaISA::swap_palshadow(&(tc->regs), true);
tc->regs.pc = tc->readMiscReg(AlphaISA::IPR_PAL_BASE) + vect();
tc->regs.npc = tc->regs.pc + sizeof(MachInst);*/
tc->setPC(PC);
tc->setNextPC(NPC);
tc->setNextNPC(NPC + sizeof(MachInst));
}
#endif
#if !FULL_SYSTEM
void TrapInstruction::invoke(ThreadContext * tc)
void PowerOnReset::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)
{
doNormalFault(tc, trapType());
doNormalFault(tc, trapType(), false);
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);
assert(lp);
@ -404,15 +632,15 @@ void SpillNNormal::invoke(ThreadContext *tc)
void FillNNormal::invoke(ThreadContext *tc)
{
doNormalFault(tc, trapType());
doNormalFault(tc, trapType(), false);
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);
assert(lp);
//The adjust the PC and NPC
//Then adjust the PC and NPC
Addr fillStart = lp->readFillStart();
tc->setPC(fillStart);
tc->setNextPC(fillStart + sizeof(MachInst));

View file

@ -42,63 +42,222 @@ namespace SparcISA
typedef uint32_t TrapType;
typedef uint32_t FaultPriority;
class SparcFault : public FaultBase
class SparcFaultBase : public FaultBase
{
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
void invoke(ThreadContext * tc);
#endif
virtual FaultName name() = 0;
virtual TrapType trapType() = 0;
virtual FaultPriority priority() = 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:
FaultName name() {return _name;}
TrapType trapType() {return _trapType;}
FaultPriority priority() {return _priority;}
FaultStat & countStat() {return _count;}
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:
FaultName name() {return _name;}
TrapType trapType() {return _trapType;}
FaultPriority priority() {return _priority;}
FaultStat & countStat() {return _count;}
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
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:
Addr vaddr;
static FaultName _name;
static TrapType _trapType;
static FaultPriority _priority;
static FaultStat _count;
public:
PageTableFault(Addr va)
: vaddr(va) {}
FaultName name() {return _name;}
TrapType trapType() {return _trapType;}
FaultPriority priority() {return _priority;}
FaultStat & countStat() {return _count;}
PageTableFault(Addr va) : vaddr(va) {}
void invoke(ThreadContext * tc);
};
@ -118,504 +277,6 @@ static inline Fault genAlignmentFault()
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

View file

@ -34,6 +34,8 @@
#include "sim/byteswap.hh"
#include "sim/serialize.hh"
#include <string.h>
using namespace SparcISA;
using namespace std;
@ -55,7 +57,7 @@ string SparcISA::getFloatRegName(RegIndex index)
void FloatRegFile::clear()
{
bzero(regSpace, sizeof(regSpace));
memset(regSpace, 0, sizeof(regSpace));
}
FloatReg FloatRegFile::readReg(int floatReg, int width)

View 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 &section)
{
}
};
}
#endif // __ARCH_SPARC_INTERRUPT_HH__

View file

@ -33,6 +33,8 @@
#include "base/trace.hh"
#include "sim/serialize.hh"
#include <string.h>
using namespace SparcISA;
using namespace std;
@ -62,7 +64,7 @@ void IntRegFile::clear()
for (x = 0; x < MaxGL; x++)
memset(regGlobals[x], 0, sizeof(IntReg) * RegsPerFrame);
for(int x = 0; x < 2 * NWindows; x++)
bzero(regSegments[x], sizeof(IntReg) * RegsPerFrame);
memset(regSegments[x], 0, sizeof(IntReg) * RegsPerFrame);
}
IntRegFile::IntRegFile()

View file

@ -346,22 +346,93 @@ decode OP default Unknown::unknown()
0x0: sra({{Rd = Rs1.sw >> (I ? SHCNT32 : Rs2<4:0>);}});
0x1: srax({{Rd = Rs1.sdw >> (I ? SHCNT64 : Rs2<5:0>);}});
}
// XXX might want a format rdipr thing here
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*/}});
0x1: Nop::membar({{/*stuff*/}});
}
default: rdasr({{
Rd = xc->readMiscRegWithEffect(RS1 + AsrStart, fault);
0x10: Priv::rdpcr({{Rd = Pcr;}});
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({{
if(NWindows - 2 - Cansave == 0)
{
@ -417,9 +488,35 @@ decode OP default Unknown::unknown()
0x6: movrg({{Rd = (Rs1.sdw > 0) ? Rs2_or_imm10 : Rd;}});
0x7: movrge({{Rd = (Rs1.sdw >= 0) ? Rs2_or_imm10 : Rd;}});
}
0x30: wrasr({{
xc->setMiscRegWithEffect(RD + AsrStart, Rs1 ^ Rs2_or_imm13);
}});
0x30: decode RD {
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 {
0x0: Priv::saved({{
assert(Cansave < NWindows - 2);
@ -440,16 +537,70 @@ decode OP default Unknown::unknown()
Otherwin = Otherwin - 1;
}});
}
0x32: Priv::wrpr({{
// XXX Need to protect with format that traps non-priv
// access
xc->setMiscRegWithEffect(RD + PrStart, Rs1 ^ Rs2_or_imm13);
}});
0x33: HPriv::wrhpr({{
// XXX Need to protect with format that traps non-priv/priv
// access
xc->setMiscRegWithEffect(RD + HprStart, Rs1 ^ Rs2_or_imm13);
}});
0x32: decode RD {
0x00: Priv::wrprtpc({{
if(Tl == 0)
return new IllegalInstruction;
else
Tpc = Rs1 ^ Rs2_or_imm13;
}});
0x01: Priv::wrprtnpc({{
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{
format BasicOperate{
0x01: fmovs({{

View file

@ -119,18 +119,34 @@ let {{
return (header_output, decoder_output, exec_output, decode_block)
}};
// Primary format for integer operate instructions:
def format Priv(code, *opt_flags) {{
checkCode = "!(Pstate<2:2> || Hpstate<2:2>)"
checkCode = "!(Pstate<2:> || Hpstate<2:>)"
(header_output, decoder_output,
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) {{
checkCode = "!Hpstate<2:2>"
(header_output, decoder_output,
exec_output, decode_block) = doPrivFormat(code,
checkCode, name, Name, opt_flags + ('IprAccessOp',))
checkCode, name, Name, opt_flags)
}};

View file

@ -54,6 +54,7 @@ output decoder {{
#if defined(linux)
#include <fenv.h>
#endif
#include <algorithm>
using namespace SparcISA;
}};

View file

@ -80,8 +80,6 @@ def operands {{
'Frs2': ('FloatReg', 'df', 'dfpr(RS2)', 'IsFloating', 12),
'NPC': ('NPC', 'udw', None, ( None, None, 'IsControl' ), 31),
'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),
'R1': ('IntReg', 'udw', '1', None, 7),
'R15': ('IntReg', 'udw', '15', 'IsInteger', 8),
@ -91,24 +89,42 @@ def operands {{
'Y': ('ControlReg', 'udw', 'MISCREG_Y', None, 40),
'Ccr': ('ControlReg', 'udw', 'MISCREG_CCR', None, 41),
'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),
'Tnpc': ('ControlReg', 'udw', 'MISCREG_TNPC', None, 44),
'Tstate': ('ControlReg', 'udw', 'MISCREG_TSTATE', None, 45),
'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 46),
'Hpstate': ('ControlReg', 'udw', 'MISCREG_HPSTATE', None, 47),
'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 48),
'Tpc': ('ControlReg', 'udw', 'MISCREG_TPC', None, 53),
'Tnpc': ('ControlReg', 'udw', 'MISCREG_TNPC', None, 54),
'Tstate': ('ControlReg', 'udw', 'MISCREG_TSTATE', None, 55),
'Tt': ('ControlReg', 'udw', 'MISCREG_TT', None, 56),
'Tick': ('ControlReg', 'udw', 'MISCREG_TICK', None, 57),
'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),
'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 50),
'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 51),
'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 52),
'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 53),
'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 54),
'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 55),
'Hpstate': ('ControlReg', 'udw', 'MISCREG_HPSTATE', None, 69),
'Htstate': ('ControlReg', 'udw', 'MISCREG_HTSTATE', None, 70),
'Hintp': ('ControlReg', 'udw', 'MISCREG_HINTP', None, 71),
'Htba': ('ControlReg', 'udw', 'MISCREG_HTBA', None, 72),
'HstickCmpr': ('ControlReg', 'udw', 'MISCREG_HSTICK_CMPR', None, 73),
'Hver': ('ControlReg', 'udw', 'MISCREG_HVER', None, 74),
'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 56),
'Gsr': ('ControlReg', 'udw', 'MISCREG_GSR', None, 57),
'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 80),
# Mem gets a large number so it's always last
'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 100)

View 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__

View file

@ -29,11 +29,18 @@
* Ali Saidi
*/
#include "arch/sparc/asi.hh"
#include "arch/sparc/miscregfile.hh"
#include "base/bitfield.hh"
#include "base/trace.hh"
#include "config/full_system.hh"
#include "cpu/base.hh"
#include "cpu/thread_context.hh"
#if FULL_SYSTEM
#include "arch/sparc/system.hh"
#endif
using namespace SparcISA;
using namespace std;
@ -55,66 +62,41 @@ string SparcISA::getMiscRegName(RegIndex 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()
{
pstateFields.pef = 0; //No FPU
//pstateFields.pef = 1; //FPU
#if FULL_SYSTEM
//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] = power_on_reset;
pstate = 0; // fields 0 but pef
pstateFields.pef = 1;
y = 0;
ccr = 0;
asi = 0;
tick = 0;
fprs = 0;
gsr = 0;
softint = 0;
tick_cmpr = 0;
stick = 0;
stick_cmpr = 0;
memset(tpc, 0, sizeof(tpc));
memset(tnpc, 0, sizeof(tnpc));
memset(tstate, 0, sizeof(tstate));
memset(tt, 0, sizeof(tt));
pstate = 0;
tl = 0;
pil = 0;
cwp = 0;
cansave = 0;
canrestore = 0;
cleanwin = 0;
otherwin = 0;
wstate = 0;
gl = 0;
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
/* //This sets up the initial state of the processor for usermode processes
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
memset(htstate, 0, sizeof(htstate));
hintp = 0;
htba = 0;
hstick_cmpr = 0;
strandStatusReg = 0;
fsr = 0;
implicitInstAsi = ASI_PRIMARY;
implicitDataAsi = ASI_PRIMARY;
}
MiscReg MiscRegFile::readReg(int miscReg)
@ -131,8 +113,9 @@ MiscReg MiscRegFile::readReg(int miscReg)
case MISCREG_TICK:
return tick;
case MISCREG_PCR:
panic("PCR not implemented\n");
case MISCREG_PIC:
panic("ASR number %d not implemented\n", miscReg - AsrStart);
panic("PIC not implemented\n");
case MISCREG_GSR:
return gsr;
case MISCREG_SOFTINT:
@ -207,17 +190,27 @@ MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc)
switch (miscReg) {
case MISCREG_TICK:
case MISCREG_PRIVTICK:
return tc->getCpuPtr()->curCycle() - tickFields.counter |
tickFields.npt << 63;
return tc->getCpuPtr()->curCycle() - (tick & mask(63)) |
(tick & ~(mask(63))) << 63;
case MISCREG_FPRS:
panic("FPU not implemented\n");
case MISCREG_PCR:
case MISCREG_PIC:
panic("Performance Instrumentation not impl\n");
/** Floating Point Status Register */
case MISCREG_FSR:
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);
}
@ -241,8 +234,9 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val)
tick = val;
break;
case MISCREG_PCR:
panic("PCR not implemented\n");
case MISCREG_PIC:
panic("ASR number %d not implemented\n", miscReg - AsrStart);
panic("PIC not implemented\n");
case MISCREG_GSR:
gsr = val;
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,
const MiscReg &val, ThreadContext * tc)
{
const uint64_t Bit64 = (1ULL << 63);
#if FULL_SYSTEM
uint64_t time;
SparcSystem *sys;
#endif
switch (miscReg) {
case MISCREG_TICK:
tickFields.counter = tc->getCpuPtr()->curCycle() - val & ~Bit64;
tickFields.npt = val & Bit64 ? 1 : 0;
tick = tc->getCpuPtr()->curCycle() - val & ~Bit64;
tick |= val & Bit64;
break;
case MISCREG_FPRS:
//Configure the fpu based on the fprs
@ -352,12 +374,84 @@ void MiscRegFile::setRegWithEffect(int miscReg,
case MISCREG_PCR:
//Set up performance counting based on pcr value
break;
case MISCREG_PSTATE:
pstate = val;
setImplicitAsis();
return;
case MISCREG_TL:
tl = val;
setImplicitAsis();
return;
case MISCREG_CWP:
tc->changeRegFileContext(CONTEXT_CWP, val);
break;
case MISCREG_GL:
tc->changeRegFileContext(CONTEXT_GLOBALS, val);
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);
}
@ -389,6 +483,8 @@ void MiscRegFile::serialize(std::ostream & os)
SERIALIZE_ARRAY(htstate, MaxTL);
SERIALIZE_SCALAR(htba);
SERIALIZE_SCALAR(hstick_cmpr);
SERIALIZE_SCALAR((int)implicitInstAsi);
SERIALIZE_SCALAR((int)implicitDataAsi);
}
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_SCALAR(htba);
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

View file

@ -32,9 +32,11 @@
#ifndef __ARCH_SPARC_MISCREGFILE_HH__
#define __ARCH_SPARC_MISCREGFILE_HH__
#include "arch/sparc/asi.hh"
#include "arch/sparc/faults.hh"
#include "arch/sparc/isa_traits.hh"
#include "arch/sparc/types.hh"
#include "cpu/cpuevent.hh"
#include <string>
@ -44,59 +46,53 @@ namespace SparcISA
//These functions map register indices to names
std::string getMiscRegName(RegIndex);
const int AsrStart = 0;
const int PrStart = 32;
const int HprStart = 64;
const int MiscStart = 96;
enum MiscRegIndex
{
/** Ancillary State Registers */
MISCREG_Y = AsrStart + 0,
MISCREG_CCR = AsrStart + 2,
MISCREG_ASI = AsrStart + 3,
MISCREG_TICK = AsrStart + 4,
MISCREG_FPRS = AsrStart + 6,
MISCREG_PCR = AsrStart + 16,
MISCREG_PIC = AsrStart + 17,
MISCREG_GSR = AsrStart + 19,
MISCREG_SOFTINT_SET = AsrStart + 20,
MISCREG_SOFTINT_CLR = AsrStart + 21,
MISCREG_SOFTINT = AsrStart + 22,
MISCREG_TICK_CMPR = AsrStart + 23,
MISCREG_STICK = AsrStart + 24,
MISCREG_STICK_CMPR = AsrStart + 25,
MISCREG_Y,
MISCREG_CCR,
MISCREG_ASI,
MISCREG_TICK,
MISCREG_FPRS,
MISCREG_PCR,
MISCREG_PIC,
MISCREG_GSR,
MISCREG_SOFTINT_SET,
MISCREG_SOFTINT_CLR,
MISCREG_SOFTINT,
MISCREG_TICK_CMPR,
MISCREG_STICK,
MISCREG_STICK_CMPR,
/** Privilged Registers */
MISCREG_TPC = PrStart + 0,
MISCREG_TNPC = PrStart + 1,
MISCREG_TSTATE = PrStart + 2,
MISCREG_TT = PrStart + 3,
MISCREG_PRIVTICK = PrStart + 4,
MISCREG_TBA = PrStart + 5,
MISCREG_PSTATE = PrStart + 6,
MISCREG_TL = PrStart + 7,
MISCREG_PIL = PrStart + 8,
MISCREG_CWP = PrStart + 9,
MISCREG_CANSAVE = PrStart + 10,
MISCREG_CANRESTORE = PrStart + 11,
MISCREG_CLEANWIN = PrStart + 12,
MISCREG_OTHERWIN = PrStart + 13,
MISCREG_WSTATE = PrStart + 14,
MISCREG_GL = PrStart + 16,
MISCREG_TPC,
MISCREG_TNPC,
MISCREG_TSTATE,
MISCREG_TT,
MISCREG_PRIVTICK,
MISCREG_TBA,
MISCREG_PSTATE,
MISCREG_TL,
MISCREG_PIL,
MISCREG_CWP,
MISCREG_CANSAVE,
MISCREG_CANRESTORE,
MISCREG_CLEANWIN,
MISCREG_OTHERWIN,
MISCREG_WSTATE,
MISCREG_GL,
/** Hyper privileged registers */
MISCREG_HPSTATE = HprStart + 0,
MISCREG_HTSTATE = HprStart + 1,
MISCREG_HINTP = HprStart + 3,
MISCREG_HTBA = HprStart + 5,
MISCREG_HVER = HprStart + 6,
MISCREG_STRAND_STS_REG = HprStart + 16,
MISCREG_HSTICK_CMPR = HprStart + 31,
MISCREG_HPSTATE,
MISCREG_HTSTATE,
MISCREG_HINTP,
MISCREG_HTBA,
MISCREG_HVER,
MISCREG_STRAND_STS_REG,
MISCREG_HSTICK_CMPR,
/** Floating Point Status Register */
MISCREG_FSR = MiscStart + 0
MISCREG_FSR
};
// The control registers, broken out into fields
@ -105,93 +101,16 @@ namespace SparcISA
private:
/* ASR Registers */
union {
uint64_t y; // Y (used in obsolete multiplication)
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;
};
uint64_t y; // Y (used in obsolete multiplication)
uint8_t ccr; // Condition Code Register
uint8_t asi; // Address Space Identifier
union {
uint64_t tick; // Hardware clock-tick counter
struct {
int64_t counter:63; // Clock-tick count
uint64_t npt:1; // Non-priveleged trap
} tickFields;
};
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;
};
uint64_t tick; // Hardware clock-tick counter
uint8_t fprs; // Floating-Point Register State
uint64_t gsr; // General Status Register
uint64_t softint;
uint64_t tick_cmpr; // Hardware tick compare registers
uint64_t stick; // Hardware clock-tick counter
uint64_t stick_cmpr; // Hardware tick compare registers
/* Privileged Registers */
@ -199,37 +118,12 @@ namespace SparcISA
// previous trap level)
uint64_t tnpc[MaxTL]; // Trap Next Program Counter (value from
// previous trap level)
union {
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];
};
uint64_t tstate[MaxTL]; // Trap State
uint16_t tt[MaxTL]; // Trap Type (Type of trap which occured
// on the previous level)
uint64_t tba; // Trap Base Address
union {
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;
};
uint16_t pstate; // Process State Register
uint8_t tl; // Trap Level
uint8_t pil; // Process Interrupt Register
uint8_t cwp; // Current Window Pointer
@ -237,97 +131,23 @@ namespace SparcISA
uint8_t canrestore; // Restorable windows
uint8_t cleanwin; // Clean windows
uint8_t otherwin; // Other windows
union {
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 wstate; // Window State
uint8_t gl; // Global level register
/** Hyperprivileged Registers */
union {
uint64_t hpstate; // Hyperprivileged 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 hpstate; // Hyperprivileged State Register
uint64_t htstate[MaxTL];// Hyperprivileged Trap State Register
uint64_t hintp;
uint64_t htba; // Hyperprivileged Trap Base Address register
union {
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 htba; // Hyperprivileged Trap Base Address register
uint64_t hstick_cmpr; // Hardware tick compare registers
uint64_t strandStatusReg;// Per strand status register
/** Floating point misc registers. */
union {
uint64_t fsr; // Floating-Point State Register
struct {
union {
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;
};
uint64_t fsr; // Floating-Point State Register
ASI implicitInstAsi;
ASI implicitDataAsi;
// These need to check the int_dis field and if 0 then
// set appropriate bit in softint and checkinterrutps on the cpu
@ -349,12 +169,6 @@ namespace SparcISA
typedef CpuEventWrapper<MiscRegFile,
&MiscRegFile::processHSTickCompare> HSTickCompareEvent;
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
public:
@ -374,6 +188,16 @@ namespace SparcISA
void setRegWithEffect(int miscReg,
const MiscReg &val, ThreadContext * tc);
ASI getInstAsid()
{
return implicitInstAsi;
}
ASI getDataAsid()
{
return implicitDataAsi;
}
void serialize(std::ostream & os);
void unserialize(Checkpoint * cp, const std::string & section);
@ -382,9 +206,10 @@ namespace SparcISA
protected:
bool isHyperPriv() { return hpstateFields.hpriv; }
bool isPriv() { return hpstateFields.hpriv || pstateFields.priv; }
bool isHyperPriv() { return (hpstate & (1 << 2)); }
bool isPriv() { return (hpstate & (1 << 2)) || (pstate & (1 << 2)); }
bool isNonPriv() { return !isPriv(); }
inline void setImplicitAsis();
};
}

View file

@ -29,6 +29,7 @@
* Ali Saidi
*/
#include "arch/sparc/asi.hh"
#include "arch/sparc/isa_traits.hh"
#include "arch/sparc/process.hh"
#include "base/loader/object_file.hh"
@ -105,6 +106,8 @@ SparcLiveProcess::startup()
threadContexts[0]->setMiscReg(MISCREG_WSTATE, 0);
//Set the trap level to 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)

View file

@ -79,24 +79,20 @@ MiscReg RegFile::readMiscReg(int miscReg)
return miscRegFile.readReg(miscReg);
}
MiscReg RegFile::readMiscRegWithEffect(int miscReg,
Fault &fault, ThreadContext *tc)
MiscReg RegFile::readMiscRegWithEffect(int miscReg, ThreadContext *tc)
{
fault = NoFault;
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);
return NoFault;
}
Fault RegFile::setMiscRegWithEffect(int miscReg, const MiscReg &val,
void RegFile::setMiscRegWithEffect(int miscReg, const MiscReg &val,
ThreadContext * tc)
{
miscRegFile.setRegWithEffect(miscReg, val, tc);
return NoFault;
}
FloatReg RegFile::readFloatReg(int floatReg, int width)
@ -122,27 +118,26 @@ FloatRegBits RegFile::readFloatRegBits(int floatReg)
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
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
return floatRegFile.setRegBits(floatReg, val,
FloatRegFile::SingleWidth);
floatRegFile.setRegBits(floatReg, val, FloatRegFile::SingleWidth);
}
IntReg RegFile::readIntReg(int intReg)
@ -150,9 +145,9 @@ IntReg RegFile::readIntReg(int 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)

View file

@ -32,7 +32,6 @@
#ifndef __ARCH_SPARC_REGFILE_HH__
#define __ARCH_SPARC_REGFILE_HH__
#include "arch/sparc/faults.hh"
#include "arch/sparc/floatregfile.hh"
#include "arch/sparc/intregfile.hh"
#include "arch/sparc/isa_traits.hh"
@ -76,14 +75,23 @@ namespace SparcISA
MiscReg readMiscReg(int miscReg);
MiscReg readMiscRegWithEffect(int miscReg,
Fault &fault, ThreadContext *tc);
MiscReg readMiscRegWithEffect(int miscReg, 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);
ASI instAsid()
{
return miscRegFile.getInstAsid();
}
ASI dataAsid()
{
return miscRegFile.getDataAsid();
}
FloatReg readFloatReg(int floatReg, int width);
FloatReg readFloatReg(int floatReg);
@ -92,17 +100,17 @@ namespace SparcISA
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);
Fault setIntReg(int intReg, const IntReg &val);
void setIntReg(int intReg, const IntReg &val);
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);

View 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");
}

View 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__ */

View 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 &reg, 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
}

View file

@ -35,87 +35,90 @@
#include "cpu/static_inst.hh"
class ThreadContext;
class StackTrace;
class ProcessInfo
namespace SparcISA
{
private:
ThreadContext *tc;
class StackTrace;
int thread_info_size;
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 &reg, 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()
class ProcessInfo
{
tc = 0;
stack.clear();
}
private:
ThreadContext *tc;
bool valid() const { return tc != NULL; }
bool trace(ThreadContext *tc, StaticInstPtr inst);
int thread_info_size;
int task_struct_size;
int task_off;
int pid_off;
int name_off;
public:
const std::vector<Addr> &getstack() const { return stack; }
public:
ProcessInfo(ThreadContext *_tc);
static const int user = 1;
static const int console = 2;
static const int unknown = 3;
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 &reg, 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
private:
void dump();
private:
void dump();
public:
void dprintf() { if (DTRACE(Stack)) dump(); }
public:
void dprintf() { if (DTRACE(Stack)) dump(); }
#else
public:
void dprintf() {}
public:
void dprintf() {}
#endif
};
};
inline bool
StackTrace::trace(ThreadContext *tc, StaticInstPtr inst)
{
if (!inst->isCall() && !inst->isReturn())
return false;
inline bool
StackTrace::trace(ThreadContext *tc, StaticInstPtr inst)
{
if (!inst->isCall() && !inst->isReturn())
return false;
if (valid())
clear();
if (valid())
clear();
trace(tc, !inst->isReturn());
return true;
trace(tc, !inst->isReturn());
return true;
}
}
#endif // __ARCH_SPARC_STACKTRACE_HH__

View file

@ -42,42 +42,49 @@
using namespace BigEndianGuest;
SparcSystem::SparcSystem(Params *p)
: System(p), sysTick(0)
: System(p), sysTick(0),funcRomPort(p->name + "-fport")
{
resetSymtab = new SymbolTable;
hypervisorSymtab = 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.
*/
// Read the reset binary
reset = createObjectFile(params()->reset_bin);
reset = createObjectFile(params()->reset_bin, true);
if (reset == NULL)
fatal("Could not load reset binary %s", params()->reset_bin);
// Read the openboot binary
openboot = createObjectFile(params()->openboot_bin);
openboot = createObjectFile(params()->openboot_bin, true);
if (openboot == NULL)
fatal("Could not load openboot bianry %s", params()->openboot_bin);
// Read the hypervisor binary
hypervisor = createObjectFile(params()->hypervisor_bin);
hypervisor = createObjectFile(params()->hypervisor_bin, true);
if (hypervisor == NULL)
fatal("Could not load hypervisor binary %s", params()->hypervisor_bin);
// Load reset binary into memory
reset->loadSections(&functionalPort, SparcISA::LoadAddrMask);
reset->setTextBase(params()->reset_addr);
reset->loadSections(&funcRomPort);
// Load the openboot binary
openboot->loadSections(&functionalPort, SparcISA::LoadAddrMask);
openboot->setTextBase(params()->openboot_addr);
openboot->loadSections(&funcRomPort);
// Load the hypervisor binary
hypervisor->loadSections(&functionalPort, SparcISA::LoadAddrMask);
hypervisor->setTextBase(params()->hypervisor_addr);
hypervisor->loadSections(&funcRomPort);
// load symbols
if (!reset->loadGlobalSymbols(reset))
if (!reset->loadGlobalSymbols(resetSymtab))
panic("could not load reset symbols\n");
if (!openboot->loadGlobalSymbols(openbootSymtab))
@ -141,13 +148,19 @@ SparcSystem::unserialize(Checkpoint *cp, const std::string &section)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcSystem)
SimObjectParam<PhysicalMemory *> physmem;
SimObjectParam<PhysicalMemory *> rom;
SimpleEnumParam<System::MemoryMode> mem_mode;
Param<Addr> reset_addr;
Param<Addr> hypervisor_addr;
Param<Addr> openboot_addr;
Param<std::string> kernel;
Param<std::string> reset_bin;
Param<std::string> hypervisor_bin;
Param<std::string> openboot_bin;
Param<Tick> boot_cpu_frequency;
Param<std::string> boot_osflags;
Param<std::string> readfile;
Param<unsigned int> init_param;
@ -156,20 +169,24 @@ END_DECLARE_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(rom, "ROM for boot code"),
INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
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(reset_bin, "file that contains the reset code"),
INIT_PARAM(hypervisor_bin, "file that contains the hypervisor 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",
"a"),
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(system_type, "Type of system we are emulating", 34),
INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10)
INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0)
END_INIT_SIM_OBJECT_PARAMS(SparcSystem)
@ -179,16 +196,18 @@ CREATE_SIM_OBJECT(SparcSystem)
p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem;
p->rom = rom;
p->mem_mode = mem_mode;
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->hypervisor_bin = hypervisor_bin;
p->openboot_bin = openboot_bin;
p->boot_osflags = boot_osflags;
p->init_param = init_param;
p->readfile = readfile;
p->system_type = system_type;
p->system_rev = system_rev;
return new SparcSystem(p);
}

View file

@ -45,12 +45,14 @@ class SparcSystem : public System
public:
struct Params : public System::Params
{
PhysicalMemory *rom;
Addr reset_addr;
Addr hypervisor_addr;
Addr openboot_addr;
std::string reset_bin;
std::string hypervison_bin;
std::string hypervisor_bin;
std::string openboot_bin;
std::string boot_osflags;
uint64_t system_type;
uint64_t system_rev;
};
SparcSystem(Params *p);
@ -87,6 +89,9 @@ class SparcSystem : public System
/** System Tick for syncronized tick across all cpus. */
Tick sysTick;
/** functional port to ROM */
FunctionalPort funcRomPort;
protected:
const Params *params() const { return (const Params *)_params; }
@ -111,8 +116,11 @@ class SparcSystem : public System
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

79
src/arch/sparc/tlb.cc Normal file
View 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)
}

View file

@ -31,5 +31,47 @@
#ifndef __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__

View file

@ -31,6 +31,7 @@
#ifndef __ARCH_SPARC_UTILITY_HH__
#define __ARCH_SPARC_UTILITY_HH__
#include "arch/sparc/faults.hh"
#include "arch/sparc/isa_traits.hh"
#include "base/misc.hh"
#include "base/bitfield.hh"
@ -38,6 +39,14 @@
namespace SparcISA
{
static inline bool
inUserMode(ThreadContext *tc)
{
return !(tc->readMiscReg(MISCREG_PSTATE & (1 << 2)) ||
tc->readMiscReg(MISCREG_HPSTATE & (1 << 2)));
}
inline ExtMachInst
makeExtMI(MachInst inst, ThreadContext * xc) {
ExtMachInst emi = (unsigned MachInst) inst;
@ -99,6 +108,12 @@ namespace SparcISA
template <class TC>
void zeroRegisters(TC *tc);
inline void initCPU(ThreadContext *tc, int cpuId)
{
static Fault por = new PowerOnReset();
por->invoke(tc);
}
} // namespace SparcISA
#endif

View file

@ -32,135 +32,47 @@
#include <string>
#include "arch/alpha/ev5.hh"
#include "arch/alpha/vtophys.hh"
#include "arch/sparc/vtophys.hh"
#include "base/chunk_generator.hh"
#include "base/trace.hh"
#include "cpu/thread_context.hh"
#include "mem/vport.hh"
using namespace std;
using namespace AlphaISA;
AlphaISA::PageTableEntry
AlphaISA::kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vaddr)
namespace SparcISA
{
Addr level1_pte = ptbr + vaddr.level1();
AlphaISA::PageTableEntry level1 = mem->read<uint64_t>(level1_pte);
if (!level1.valid()) {
DPRINTF(VtoPhys, "level 1 PTE not valid, va = %#\n", vaddr);
return 0;
}
Addr level2_pte = level1.paddr() + vaddr.level2();
AlphaISA::PageTableEntry level2 = mem->read<uint64_t>(level2_pte);
if (!level2.valid()) {
DPRINTF(VtoPhys, "level 2 PTE not valid, va = %#x\n", vaddr);
return 0;
}
Addr level3_pte = level2.paddr() + vaddr.level3();
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;
}
return level3;
}
Addr
AlphaISA::vtophys(Addr vaddr)
{
Addr paddr = 0;
if (AlphaISA::IsUSeg(vaddr))
DPRINTF(VtoPhys, "vtophys: invalid vaddr %#x", vaddr);
else if (AlphaISA::IsK0Seg(vaddr))
paddr = AlphaISA::K0Seg2Phys(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())
PageTableEntry kernel_pte_lookup(FunctionalPort *mem,
Addr ptbr, VAddr vaddr)
{
PageTableEntry pte(4);
return pte;
}
Addr vtophys(Addr vaddr)
{
return vaddr;
}
Addr vtophys(ThreadContext *tc, Addr addr)
{
return addr;
}
void CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen)
{
}
void CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen)
{
}
void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen)
{
}
void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr)
{
vp->writeBlob(gen.addr(), (uint8_t*)src, gen.size());
src += gen.size();
}
tc->delVirtPort(vp);
}

View file

@ -45,6 +45,7 @@
#include "base/loader/ecoff_object.hh"
#include "base/loader/aout_object.hh"
#include "base/loader/elf_object.hh"
#include "base/loader/raw_object.hh"
#include "mem/translating_port.hh"
@ -107,7 +108,7 @@ ObjectFile::close()
ObjectFile *
createObjectFile(const string &fname)
createObjectFile(const string &fname, bool raw)
{
// open the file
int fd = open(fname.c_str(), O_RDONLY);
@ -141,6 +142,9 @@ createObjectFile(const string &fname)
return fileObj;
}
if (raw)
return RawObject::tryFile(fname, fd, len, fileData);
// don't know what it is
close(fd);
munmap(fileData, len);

View file

@ -114,9 +114,11 @@ class ObjectFile
size_t textSize() const { return text.size; }
size_t dataSize() const { return data.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__

View 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;
}

View 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__

View file

@ -30,6 +30,9 @@
#include <sys/ioctl.h>
#include <sys/types.h>
#if defined(__sun__)
#include <sys/file.h>
#endif
#include <fcntl.h>
#include <signal.h>

View file

@ -32,6 +32,10 @@
#include <cstdlib>
#include <cmath>
#if defined(__sun__)
#include <ieeefp.h>
#endif
#include "sim/param.hh"
#include "base/random.hh"
#include "base/trace.hh"
@ -65,12 +69,27 @@ getLong()
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
getUniform(int64_t min, int64_t max)
{
double r;
r = drand48() * (max-min) + min;
return (int64_t)round(r);
return (int64_t)m5round(r);
}
uint64_t
@ -78,7 +97,8 @@ getUniformPos(uint64_t min, uint64_t max)
{
double r;
r = drand48() * (max-min) + min;
return (uint64_t)round(r);
return (uint64_t)m5round(r);
}

View file

@ -36,6 +36,7 @@
long getLong();
double getDouble();
double m5random(double r);
uint64_t getUniformPos(uint64_t min, uint64_t max);
int64_t getUniform(int64_t min, int64_t max);

View file

@ -123,7 +123,6 @@
#include "arch/vtophys.hh"
#include "base/intmath.hh"
#include "base/kgdb.h"
#include "base/remote_gdb.hh"
#include "base/socket.hh"
#include "base/trace.hh"
@ -138,18 +137,18 @@ using namespace std;
using namespace TheISA;
#ifndef NDEBUG
vector<RemoteGDB *> debuggers;
int current_debugger = -1;
vector<BaseRemoteGDB *> debuggers;
void
debugger()
{
static int current_debugger = -1;
if (current_debugger >= 0 && current_debugger < debuggers.size()) {
RemoteGDB *gdb = debuggers[current_debugger];
BaseRemoteGDB *gdb = debuggers[current_debugger];
if (!gdb->isattached())
gdb->listener->accept();
if (gdb->isattached())
gdb->trap(ALPHA_KENTRY_IF);
gdb->trap(SIGILL);
}
}
#endif
@ -169,7 +168,7 @@ GDBListener::Event::process(int revent)
listener->accept();
}
GDBListener::GDBListener(RemoteGDB *g, int p)
GDBListener::GDBListener(BaseRemoteGDB *g, int p)
: event(NULL), gdb(g), port(p)
{
assert(!gdb->listener);
@ -229,55 +228,46 @@ GDBListener::accept()
}
}
///////////////////////////////////////////////////////////
//
//
//
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)
BaseRemoteGDB::Event::Event(BaseRemoteGDB *g, int fd, int e)
: PollEvent(fd, e), gdb(g)
{}
void
RemoteGDB::Event::process(int revent)
BaseRemoteGDB::Event::process(int revent)
{
if (revent & POLLIN)
gdb->trap(ALPHA_KENTRY_IF);
gdb->trap(SIGILL);
else if (revent & POLLNVAL)
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),
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)
delete event;
}
string
RemoteGDB::name()
BaseRemoteGDB::name()
{
return system->name() + ".remote_gdb";
}
bool
RemoteGDB::isattached()
BaseRemoteGDB::isattached()
{ return attached; }
void
RemoteGDB::attach(int f)
BaseRemoteGDB::attach(int f)
{
fd = f;
@ -289,7 +279,7 @@ RemoteGDB::attach(int f)
}
void
RemoteGDB::detach()
BaseRemoteGDB::detach()
{
attached = false;
close(fd);
@ -300,250 +290,50 @@ RemoteGDB::detach()
}
const char *
gdb_command(char cmd)
BaseRemoteGDB::gdb_command(char cmd)
{
switch (cmd) {
case KGDB_SIGNAL: return "KGDB_SIGNAL";
case KGDB_SET_BAUD: return "KGDB_SET_BAUD";
case KGDB_SET_BREAK: return "KGDB_SET_BREAK";
case KGDB_CONT: return "KGDB_CONT";
case KGDB_ASYNC_CONT: return "KGDB_ASYNC_CONT";
case KGDB_DEBUG: return "KGDB_DEBUG";
case KGDB_DETACH: return "KGDB_DETACH";
case KGDB_REG_R: return "KGDB_REG_R";
case KGDB_REG_W: return "KGDB_REG_W";
case KGDB_SET_THREAD: return "KGDB_SET_THREAD";
case KGDB_CYCLE_STEP: return "KGDB_CYCLE_STEP";
case KGDB_SIG_CYCLE_STEP: return "KGDB_SIG_CYCLE_STEP";
case KGDB_KILL: return "KGDB_KILL";
case KGDB_MEM_W: return "KGDB_MEM_W";
case KGDB_MEM_R: return "KGDB_MEM_R";
case KGDB_SET_REG: return "KGDB_SET_REG";
case KGDB_READ_REG: return "KGDB_READ_REG";
case KGDB_QUERY_VAR: return "KGDB_QUERY_VAR";
case KGDB_SET_VAR: return "KGDB_SET_VAR";
case KGDB_RESET: return "KGDB_RESET";
case KGDB_STEP: return "KGDB_STEP";
case KGDB_ASYNC_STEP: return "KGDB_ASYNC_STEP";
case KGDB_THREAD_ALIVE: return "KGDB_THREAD_ALIVE";
case KGDB_TARGET_EXIT: return "KGDB_TARGET_EXIT";
case KGDB_BINARY_DLOAD: return "KGDB_BINARY_DLOAD";
case KGDB_CLR_HW_BKPT: return "KGDB_CLR_HW_BKPT";
case KGDB_SET_HW_BKPT: return "KGDB_SET_HW_BKPT";
case KGDB_START: return "KGDB_START";
case KGDB_END: return "KGDB_END";
case KGDB_GOODP: return "KGDB_GOODP";
case KGDB_BADP: return "KGDB_BADP";
case GDBSignal: return "KGDB_SIGNAL";
case GDBSetBaud: return "KGDB_SET_BAUD";
case GDBSetBreak: return "KGDB_SET_BREAK";
case GDBCont: return "KGDB_CONT";
case GDBAsyncCont: return "KGDB_ASYNC_CONT";
case GDBDebug: return "KGDB_DEBUG";
case GDBDetach: return "KGDB_DETACH";
case GDBRegR: return "KGDB_REG_R";
case GDBRegW: return "KGDB_REG_W";
case GDBSetThread: return "KGDB_SET_THREAD";
case GDBCycleStep: return "KGDB_CYCLE_STEP";
case GDBSigCycleStep: return "KGDB_SIG_CYCLE_STEP";
case GDBKill: return "KGDB_KILL";
case GDBMemW: return "KGDB_MEM_W";
case GDBMemR: return "KGDB_MEM_R";
case GDBSetReg: return "KGDB_SET_REG";
case GDBReadReg: return "KGDB_READ_REG";
case GDBQueryVar: return "KGDB_QUERY_VAR";
case GDBSetVar: return "KGDB_SET_VAR";
case GDBReset: return "KGDB_RESET";
case GDBStep: return "KGDB_STEP";
case GDBAsyncStep: return "KGDB_ASYNC_STEP";
case GDBThreadAlive: return "KGDB_THREAD_ALIVE";
case GDBTargetExit: return "KGDB_TARGET_EXIT";
case GDBBinaryDload: return "KGDB_BINARY_DLOAD";
case GDBClrHwBkpt: return "KGDB_CLR_HW_BKPT";
case GDBSetHwBkpt: return "KGDB_SET_HW_BKPT";
case GDBStart: return "KGDB_START";
case GDBEnd: return "KGDB_END";
case GDBGoodP: return "KGDB_GOODP";
case GDBBadP: return "KGDB_BADP";
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
RemoteGDB::getbyte()
BaseRemoteGDB::getbyte()
{
uint8_t b;
::read(fd, &b, 1);
@ -551,14 +341,14 @@ RemoteGDB::getbyte()
}
void
RemoteGDB::putbyte(uint8_t b)
BaseRemoteGDB::putbyte(uint8_t b)
{
::write(fd, &b, 1);
}
// Send a packet to gdb
void
RemoteGDB::send(const char *bp)
BaseRemoteGDB::send(const char *bp)
{
const char *p;
uint8_t csum, c;
@ -567,20 +357,26 @@ RemoteGDB::send(const char *bp)
do {
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++) {
putbyte(c);
csum += c;
}
putbyte(KGDB_END);
//Send the ending character.
putbyte(GDBEnd);
//Sent the checksum.
putbyte(i2digit(csum >> 4));
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
int
RemoteGDB::recv(char *bp, int maxlen)
BaseRemoteGDB::recv(char *bp, int maxlen)
{
char *p;
int c, csum;
@ -589,28 +385,37 @@ RemoteGDB::recv(char *bp, int maxlen)
do {
p = bp;
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;
csum += c;
*p++ = c;
len++;
}
//Mask the check sum, and terminate the command string.
csum &= 0xff;
*p = '\0';
//If the command was too long, report an error.
if (len >= maxlen) {
putbyte(KGDB_BADP);
putbyte(GDBBadP);
continue;
}
//Bring in the checksum. If the check sum matches, csum will be 0.
csum -= digit2i(getbyte()) * 16;
csum -= digit2i(getbyte());
//If the check sum was correct
if (csum == 0) {
putbyte(KGDB_GOODP);
//Report that the packet was received correctly
putbyte(GDBGoodP);
// Sequence present?
if (bp[2] == ':') {
putbyte(bp[0]);
@ -620,7 +425,8 @@ RemoteGDB::recv(char *bp, int maxlen)
}
break;
}
putbyte(KGDB_BADP);
//Otherwise, report that there was a mistake.
putbyte(GDBBadP);
} while (1);
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.
bool
RemoteGDB::read(Addr vaddr, size_t size, char *data)
BaseRemoteGDB::read(Addr vaddr, size_t size, char *data)
{
static Addr lastaddr = 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.
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 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);
context->delVirtPort(vp);
#ifdef IMB
alpha_pal_imb();
#endif
return true;
}
PCEventQueue *RemoteGDB::getPcEventQueue()
PCEventQueue *BaseRemoteGDB::getPcEventQueue()
{
return &system->pcEventQueue;
}
RemoteGDB::HardBreakpoint::HardBreakpoint(RemoteGDB *_gdb, Addr pc)
BaseRemoteGDB::HardBreakpoint::HardBreakpoint(BaseRemoteGDB *_gdb, Addr pc)
: PCEvent(_gdb->getPcEventQueue(), "HardBreakpoint Event", pc),
gdb(_gdb), refcount(0)
{
@ -707,25 +507,25 @@ RemoteGDB::HardBreakpoint::HardBreakpoint(RemoteGDB *_gdb, Addr pc)
}
void
RemoteGDB::HardBreakpoint::process(ThreadContext *tc)
BaseRemoteGDB::HardBreakpoint::process(ThreadContext *tc)
{
DPRINTF(GDBMisc, "handling hardware breakpoint at %#x\n", pc());
if (tc == gdb->context)
gdb->trap(ALPHA_KENTRY_INT);
gdb->trap(SIGTRAP);
}
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");
return insertHardBreak(addr, len);
}
bool
RemoteGDB::removeSoftBreak(Addr addr, size_t len)
BaseRemoteGDB::removeSoftBreak(Addr addr, size_t len)
{
if (len != sizeof(MachInst))
panic("invalid length\n");
@ -734,7 +534,7 @@ RemoteGDB::removeSoftBreak(Addr addr, size_t len)
}
bool
RemoteGDB::insertHardBreak(Addr addr, size_t len)
BaseRemoteGDB::insertHardBreak(Addr addr, size_t len)
{
if (len != sizeof(MachInst))
panic("invalid length\n");
@ -751,7 +551,7 @@ RemoteGDB::insertHardBreak(Addr addr, size_t len)
}
bool
RemoteGDB::removeHardBreak(Addr addr, size_t len)
BaseRemoteGDB::removeHardBreak(Addr addr, size_t len)
{
if (len != sizeof(MachInst))
panic("invalid length\n");
@ -771,8 +571,23 @@ RemoteGDB::removeHardBreak(Addr addr, size_t len)
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 *
break_type(char c)
BaseRemoteGDB::break_type(char c)
{
switch(c) {
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
// gdb/remote.c functions want to return.
bool
RemoteGDB::trap(int type)
BaseRemoteGDB::trap(int type)
{
uint64_t val;
size_t datalen, len;
char data[KGDB_BUFLEN + 1];
char buffer[sizeof(gdbregs) * 2 + 256];
char data[GDBPacketBufLen + 1];
char buffer[gdbregs.bytes() * 2 + 256];
const char *p;
char command, subcmd;
string var;
@ -823,7 +638,7 @@ RemoteGDB::trap(int type)
active = true;
else
// 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);
// Stick frame regs into our reg cache.
@ -837,24 +652,25 @@ RemoteGDB::trap(int type)
p = data + 1;
switch (command) {
case KGDB_SIGNAL:
case GDBSignal:
// if this command came from a running gdb, answer it --
// the other guy has no way of knowing if we're in or out
// 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);
continue;
case KGDB_REG_R:
if (2 * sizeof(gdbregs) > sizeof(buffer))
case GDBRegR:
if (2 * gdbregs.bytes() > sizeof(buffer))
panic("buffer too small");
mem2hex(buffer, gdbregs, sizeof(gdbregs));
mem2hex(buffer, gdbregs.regs, gdbregs.bytes());
send(buffer);
continue;
case KGDB_REG_W:
p = hex2mem(gdbregs, p, sizeof(gdbregs));
case GDBRegW:
p = hex2mem(gdbregs.regs, p, gdbregs.bytes());
if (p == NULL || *p != '\0')
send("E01");
else {
@ -864,7 +680,7 @@ RemoteGDB::trap(int type)
continue;
#if 0
case KGDB_SET_REG:
case GDBSetReg:
val = hex2i(&p);
if (*p++ != '=') {
send("E01");
@ -875,14 +691,14 @@ RemoteGDB::trap(int type)
continue;
}
gdbregs[val] = hex2i(&p);
gdbregs.regs[val] = hex2i(&p);
setregs();
send("OK");
continue;
#endif
case KGDB_MEM_R:
case GDBMemR:
val = hex2i(&p);
if (*p++ != ',') {
send("E02");
@ -914,7 +730,7 @@ RemoteGDB::trap(int type)
}
continue;
case KGDB_MEM_W:
case GDBMemW:
val = hex2i(&p);
if (*p++ != ',') {
send("E06");
@ -944,7 +760,7 @@ RemoteGDB::trap(int type)
send("E0B");
continue;
case KGDB_SET_THREAD:
case GDBSetThread:
subcmd = *p++;
val = hex2i(&p);
if (val == 0)
@ -953,14 +769,14 @@ RemoteGDB::trap(int type)
send("E01");
continue;
case KGDB_DETACH:
case KGDB_KILL:
case GDBDetach:
case GDBKill:
active = false;
clearSingleStep();
detach();
goto out;
case KGDB_ASYNC_CONT:
case GDBAsyncCont:
subcmd = hex2i(&p);
if (*p++ == ';') {
val = hex2i(&p);
@ -970,7 +786,7 @@ RemoteGDB::trap(int type)
clearSingleStep();
goto out;
case KGDB_CONT:
case GDBCont:
if (p - data < datalen) {
val = hex2i(&p);
context->setPC(val);
@ -979,7 +795,7 @@ RemoteGDB::trap(int type)
clearSingleStep();
goto out;
case KGDB_ASYNC_STEP:
case GDBAsyncStep:
subcmd = hex2i(&p);
if (*p++ == ';') {
val = hex2i(&p);
@ -989,7 +805,7 @@ RemoteGDB::trap(int type)
setSingleStep();
goto out;
case KGDB_STEP:
case GDBStep:
if (p - data < datalen) {
val = hex2i(&p);
context->setPC(val);
@ -998,7 +814,7 @@ RemoteGDB::trap(int type)
setSingleStep();
goto out;
case KGDB_CLR_HW_BKPT:
case GDBClrHwBkpt:
subcmd = *p++;
if (*p++ != ',') send("E0D");
val = hex2i(&p);
@ -1030,7 +846,7 @@ RemoteGDB::trap(int type)
send(ret ? "OK" : "E0C");
continue;
case KGDB_SET_HW_BKPT:
case GDBSetHwBkpt:
subcmd = *p++;
if (*p++ != ',') send("E0D");
val = hex2i(&p);
@ -1062,7 +878,7 @@ RemoteGDB::trap(int type)
send(ret ? "OK" : "E0C");
continue;
case KGDB_QUERY_VAR:
case GDBQueryVar:
var = string(p, datalen - 1);
if (var == "C")
send("QC0");
@ -1070,17 +886,17 @@ RemoteGDB::trap(int type)
send("");
continue;
case KGDB_SET_BAUD:
case KGDB_SET_BREAK:
case KGDB_DEBUG:
case KGDB_CYCLE_STEP:
case KGDB_SIG_CYCLE_STEP:
case KGDB_READ_REG:
case KGDB_SET_VAR:
case KGDB_RESET:
case KGDB_THREAD_ALIVE:
case KGDB_TARGET_EXIT:
case KGDB_BINARY_DLOAD:
case GDBSetBaud:
case GDBSetBreak:
case GDBDebug:
case GDBCycleStep:
case GDBSigCycleStep:
case GDBReadReg:
case GDBSetVar:
case GDBReset:
case GDBThreadAlive:
case GDBTargetExit:
case GDBBinaryDload:
// Unsupported command
DPRINTF(GDBMisc, "Unsupported command: %s\n",
gdb_command(command));
@ -1106,7 +922,7 @@ RemoteGDB::trap(int type)
// Convert a hex digit into an integer.
// This returns -1 if the argument passed is no valid hex digit.
int
digit2i(char c)
BaseRemoteGDB::digit2i(char c)
{
if (c >= '0' && c <= '9')
return (c - '0');
@ -1121,14 +937,14 @@ digit2i(char c)
// Convert the low 4 bits of an integer into an hex digit.
char
i2digit(int n)
BaseRemoteGDB::i2digit(int n)
{
return ("0123456789abcdef"[n & 0x0f]);
}
// Convert a byte array into an hex string.
void
mem2hex(void *vdst, const void *vsrc, int len)
BaseRemoteGDB::mem2hex(void *vdst, const void *vsrc, int len)
{
char *dst = (char *)vdst;
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
// returned.
const char *
hex2mem(void *vdst, const char *src, int maxlen)
BaseRemoteGDB::hex2mem(void *vdst, const char *src, int maxlen)
{
char *dst = (char *)vdst;
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
// hex digit.
Addr
hex2i(const char **srcp)
BaseRemoteGDB::hex2i(const char **srcp)
{
const char *src = *srcp;
Addr r = 0;

View file

@ -34,7 +34,6 @@
#include <map>
#include "arch/types.hh"
#include "base/kgdb.h"
#include "cpu/pc_event.hh"
#include "base/pollevent.hh"
#include "base/socket.hh"
@ -44,22 +43,72 @@ class ThreadContext;
class PhysicalMemory;
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:
friend void debugger();
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:
class Event : public PollEvent
{
protected:
RemoteGDB *gdb;
BaseRemoteGDB *gdb;
public:
Event(RemoteGDB *g, int fd, int e);
Event(BaseRemoteGDB *g, int fd, int e);
void process(int revent);
};
@ -69,8 +118,8 @@ class RemoteGDB
int number;
protected:
//The socket commands come in through
int fd;
uint64_t gdbregs[KGDB_NUMREGS];
protected:
#ifdef notyet
@ -83,6 +132,24 @@ class RemoteGDB
PhysicalMemory *pmem;
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:
uint8_t getbyte();
void putbyte(uint8_t b);
@ -92,15 +159,15 @@ class RemoteGDB
protected:
// Machine memory
bool read(Addr addr, size_t size, char *data);
bool write(Addr addr, size_t size, const char *data);
virtual bool read(Addr addr, size_t size, char *data);
virtual bool write(Addr addr, size_t size, const char *data);
template <class T> T read(Addr addr);
template <class T> void write(Addr addr, T data);
public:
RemoteGDB(System *system, ThreadContext *context);
~RemoteGDB();
BaseRemoteGDB(System *system, ThreadContext *context, size_t cacheSize);
virtual ~BaseRemoteGDB();
void replaceThreadContext(ThreadContext *tc) { context = tc; }
@ -108,16 +175,15 @@ class RemoteGDB
void detach();
bool isattached();
bool acc(Addr addr, size_t len);
static int signal(int type);
virtual bool acc(Addr addr, size_t len) = 0;
bool trap(int type);
protected:
void getregs();
void setregs();
virtual void getregs() = 0;
virtual void setregs() = 0;
void clearSingleStep();
void setSingleStep();
virtual void clearSingleStep() = 0;
virtual void setSingleStep() = 0;
PCEventQueue *getPcEventQueue();
@ -125,13 +191,13 @@ class RemoteGDB
class HardBreakpoint : public PCEvent
{
private:
RemoteGDB *gdb;
BaseRemoteGDB *gdb;
public:
int refcount;
public:
HardBreakpoint(RemoteGDB *_gdb, Addr addr);
HardBreakpoint(BaseRemoteGDB *_gdb, Addr addr);
std::string name() { return gdb->name() + ".hwbkpt"; }
virtual void process(ThreadContext *tc);
@ -148,18 +214,8 @@ class RemoteGDB
bool removeHardBreak(Addr addr, size_t len);
protected:
struct TempBreakpoint {
Addr address; // set here
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);
void clearTempBreakpoint(Addr &bkpt);
void setTempBreakpoint(Addr bkpt);
public:
std::string name();
@ -167,7 +223,7 @@ class RemoteGDB
template <class T>
inline T
RemoteGDB::read(Addr addr)
BaseRemoteGDB::read(Addr addr)
{
T temp;
read(addr, sizeof(T), (char *)&temp);
@ -176,7 +232,7 @@ RemoteGDB::read(Addr addr)
template <class T>
inline void
RemoteGDB::write(Addr addr, T data)
BaseRemoteGDB::write(Addr addr, T data)
{ write(addr, sizeof(T), (const char *)&data); }
class GDBListener
@ -197,11 +253,11 @@ class GDBListener
protected:
ListenSocket listener;
RemoteGDB *gdb;
BaseRemoteGDB *gdb;
int port;
public:
GDBListener(RemoteGDB *g, int p);
GDBListener(BaseRemoteGDB *g, int p);
~GDBListener();
void accept();

View file

@ -696,7 +696,7 @@ class ScalarBase : public DataAccess
protected:
/** The storage of this stat. */
char storage[sizeof(Storage)];
char storage[sizeof(Storage)] __attribute__ ((aligned (8)));
/** The parameters for this stat. */
Params params;
@ -1637,7 +1637,7 @@ class DistBase : public DataAccess
protected:
/** The storage for this stat. */
char storage[sizeof(Storage)];
char storage[sizeof(Storage)] __attribute__ ((aligned (8)));
/** The parameters for this stat. */
Params params;

View file

@ -36,7 +36,7 @@ namespace Stats {
* Define the storage for format flags.
* @todo Can probably shrink this.
*/
typedef u_int32_t StatFlags;
typedef uint32_t StatFlags;
/** Nothing extra to print. */
const StatFlags none = 0x00000000;

View file

@ -65,4 +65,48 @@ Time operator-(const Time &l, const Time &r);
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__

View file

@ -168,11 +168,6 @@ BaseCPU::BaseCPU(Params *p)
p->max_loads_all_threads, *counter);
}
#if FULL_SYSTEM
memset(interrupts, 0, sizeof(interrupts));
intstatus = 0;
#endif
functionTracingEnabled = false;
if (p->functionTrace) {
functionTraceStream = simout.find(csprintf("ftrace.%s", name()));
@ -259,6 +254,26 @@ BaseCPU::regStats()
#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
BaseCPU::registerThreadContexts()
@ -314,9 +329,7 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU)
}
#if FULL_SYSTEM
for (int i = 0; i < TheISA::NumInterruptLevels; ++i)
interrupts[i] = oldCPU->interrupts[i];
intstatus = oldCPU->intstatus;
interrupts = oldCPU->interrupts;
checkInterrupts = oldCPU->checkInterrupts;
for (int i = 0; i < threadContexts.size(); ++i)
@ -348,57 +361,33 @@ BaseCPU::ProfileEvent::process()
void
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;
interrupts[int_num] |= 1 << index;
intstatus |= (ULL(1) << int_num);
interrupts.post(int_num, index);
}
void
BaseCPU::clear_interrupt(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);
interrupts.clear(int_num, index);
}
void
BaseCPU::clear_interrupts()
{
DPRINTF(Interrupt, "Interrupts all cleared\n");
memset(interrupts, 0, sizeof(interrupts));
intstatus = 0;
interrupts.clear_all();
}
void
BaseCPU::serialize(std::ostream &os)
{
SERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels);
SERIALIZE_SCALAR(intstatus);
interrupts.serialize(os);
}
void
BaseCPU::unserialize(Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels);
UNSERIALIZE_SCALAR(intstatus);
interrupts.unserialize(cp, section);
}
#endif // FULL_SYSTEM

View file

@ -40,6 +40,10 @@
#include "mem/mem_object.hh"
#include "arch/isa_traits.hh"
#if FULL_SYSTEM
#include "arch/interrupts.hh"
#endif
class BranchPred;
class CheckerCPU;
class ThreadContext;
@ -73,10 +77,25 @@ class BaseCPU : public MemObject
inline Tick cycles(int numCycles) const { return clock * numCycles; }
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
protected:
uint64_t interrupts[TheISA::NumInterruptLevels];
uint64_t intstatus;
// uint64_t interrupts[TheISA::NumInterruptLevels];
// uint64_t intstatus;
TheISA::Interrupts interrupts;
public:
virtual void post_interrupt(int int_num, int index);
@ -84,15 +103,8 @@ class BaseCPU : public MemObject
virtual void clear_interrupts();
bool checkInterrupts;
bool check_interrupt(int int_num) const {
if (int_num > TheISA::NumInterruptLevels)
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; }
bool check_interrupts(ThreadContext * tc) const
{ return interrupts.check_interrupts(tc); }
class ProfileEvent : public Event
{

View file

@ -38,8 +38,8 @@
#include "cpu/thread_context.hh"
#if FULL_SYSTEM
#include "arch/kernel_stats.hh"
#include "arch/vtophys.hh"
#include "kern/kernel_stats.hh"
#endif // FULL_SYSTEM
using namespace std;
@ -72,6 +72,12 @@ CheckerCPU::CheckerCPU(Params *p)
systemPtr = NULL;
#else
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
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
CheckerCPU::setSystem(System *system)
{

View file

@ -47,9 +47,12 @@
// forward declarations
#if FULL_SYSTEM
namespace TheISA
{
class ITB;
class DTB;
}
class Processor;
class AlphaITB;
class AlphaDTB;
class PhysicalMemory;
class RemoteGDB;
@ -96,8 +99,8 @@ class CheckerCPU : public BaseCPU
struct Params : public BaseCPU::Params
{
#if FULL_SYSTEM
AlphaITB *itb;
AlphaDTB *dtb;
TheISA::ITB *itb;
TheISA::DTB *dtb;
#else
Process *process;
#endif
@ -112,10 +115,6 @@ class CheckerCPU : public BaseCPU
Process *process;
void setMemory(MemObject *mem);
MemObject *memPtr;
void setSystem(System *system);
System *systemPtr;
@ -140,8 +139,8 @@ class CheckerCPU : public BaseCPU
ThreadContext *tc;
AlphaITB *itb;
AlphaDTB *dtb;
TheISA::ITB *itb;
TheISA::DTB *dtb;
#if FULL_SYSTEM
Addr dbg_vtophys(Addr addr);
@ -301,19 +300,19 @@ class CheckerCPU : public BaseCPU
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;
miscRegIdxs.push(misc_reg);
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);
return thread->setMiscRegWithEffect(misc_reg, val);
@ -328,9 +327,6 @@ class CheckerCPU : public BaseCPU
#if FULL_SYSTEM
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); }
bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); }
#else

View file

@ -199,8 +199,13 @@ Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
// Checks both the machine instruction and the PC.
validateInst(inst);
#if THE_ISA == ALPHA_ISA
curStaticInst = StaticInst::decode(makeExtMI(machInst,
thread->readPC()));
#elif THE_ISA == SPARC_ISA
curStaticInst = StaticInst::decode(makeExtMI(machInst,
thread->getTC()));
#endif
#if FULL_SYSTEM
thread->setInst(machInst);

View file

@ -37,8 +37,10 @@
#include "cpu/thread_context.hh"
class EndQuiesceEvent;
namespace Kernel {
class Statistics;
namespace TheISA {
namespace Kernel {
class Statistics;
};
};
/**
@ -87,11 +89,12 @@ class CheckerThreadContext : public ThreadContext
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(); }
@ -248,19 +251,19 @@ class CheckerThreadContext : public ThreadContext
MiscReg readMiscReg(int misc_reg)
{ return actualTC->readMiscReg(misc_reg); }
MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
{ return actualTC->readMiscRegWithEffect(misc_reg, fault); }
MiscReg readMiscRegWithEffect(int misc_reg)
{ 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);
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);
return actualTC->setMiscRegWithEffect(misc_reg, val);
actualTC->setMiscRegWithEffect(misc_reg, val);
}
unsigned readStCondFailures()
@ -271,9 +274,6 @@ class CheckerThreadContext : public ThreadContext
checkerTC->setStCondFailures(sc_failures);
actualTC->setStCondFailures(sc_failures);
}
#if FULL_SYSTEM
bool inPalMode() { return actualTC->inPalMode(); }
#endif
// @todo: Fix this!
bool misspeculating() { return actualTC->misspeculating(); }

View file

@ -44,7 +44,7 @@ class ThreadContext;
* */
class CpuEvent : public Event
{
private:
protected:
/** type of global list of cpu events. */
typedef std::vector<CpuEvent *> CpuEventList;

View file

@ -101,14 +101,14 @@ class ExecContext {
/** Reads a miscellaneous register, handling any architectural
* side effects due to reading that register. */
MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault);
MiscReg readMiscRegWithEffect(int misc_reg);
/** 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
* 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
* for memory ops. */
@ -144,10 +144,6 @@ class ExecContext {
/** Somewhat Alpha-specific function that handles returning from
* an error or interrupt. */
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

View file

@ -33,8 +33,11 @@
#include <fstream>
#include <iomanip>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "arch/regfile.hh"
#include "arch/utility.hh"
#include "base/loader/symtab.hh"
#include "cpu/base.hh"
#include "cpu/exetrace.hh"
@ -44,10 +47,15 @@
//XXX This is temporary
#include "arch/isa_specific.hh"
#include "cpu/m5legion_interface.h"
using namespace std;
using namespace TheISA;
namespace Trace {
SharedData *shared_data = NULL;
}
////////////////////////////////////////////////////////////////////////
//
// Methods for the InstRecord object
@ -75,23 +83,19 @@ Trace::InstRecord::dump(ostream &outs)
uint64_t newVal;
static const char * prefixes[4] = {"G", "O", "L", "I"};
char buf[256];
sprintf(buf, "PC = 0x%016llx", thread->readNextPC());
outs << buf;
sprintf(buf, " NPC = 0x%016llx", thread->readNextNPC());
outs << buf;
outs << hex;
outs << "PC = " << thread->readNextPC();
outs << " NPC = " << thread->readNextNPC();
newVal = thread->readMiscReg(SparcISA::MISCREG_CCR);
if(newVal != ccr)
{
sprintf(buf, " CCR = 0x%016llx", newVal);
outs << buf;
outs << " CCR = " << newVal;
ccr = newVal;
}
newVal = thread->readMiscReg(SparcISA::MISCREG_Y);
if(newVal != y)
{
sprintf(buf, " Y = 0x%016llx", newVal);
outs << buf;
outs << " Y = " << newVal;
y = newVal;
}
for(int y = 0; y < 4; y++)
@ -102,8 +106,7 @@ Trace::InstRecord::dump(ostream &outs)
newVal = thread->readIntReg(index);
if(regs[index] != newVal)
{
sprintf(buf, " %s%d = 0x%016llx", prefixes[y], x, newVal);
outs << buf;
outs << " " << prefixes[y] << dec << x << " = " << hex << newVal;
regs[index] = newVal;
}
}
@ -113,12 +116,11 @@ Trace::InstRecord::dump(ostream &outs)
newVal = thread->readFloatRegBits(2 * y, 64);
if(floats[y] != newVal)
{
sprintf(buf, " F%d = 0x%016llx", 2 * y, newVal);
outs << buf;
outs << " F" << dec << (2 * y) << " = " << hex << newVal;
floats[y] = newVal;
}
}
outs << endl;
outs << dec << endl;
}
#endif
}
@ -222,6 +224,85 @@ Trace::InstRecord::dump(ostream &outs)
//
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);
Param<bool> exe_trace_intel_format(&exeTraceParams, "intel_format",
"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",
"print trace of which system (client or server)",
"client");
@ -296,7 +380,28 @@ Trace::InstRecord::setParams()
flags[PRINT_REG_DELTA] = exe_trace_print_reg_delta;
flags[PC_SYMBOL] = exe_trace_pc_symbol;
flags[INTEL_FORMAT] = exe_trace_intel_format;
flags[LEGION_LOCKSTEP] = exe_trace_legion_lockstep;
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

View file

@ -150,6 +150,7 @@ class InstRecord : public Record
PRINT_REG_DELTA,
PC_SYMBOL,
INTEL_FORMAT,
LEGION_LOCKSTEP,
NUM_BITS
};

View file

@ -32,8 +32,6 @@
#ifndef __STD_TYPES_HH__
#define __STD_TYPES_HH__
#include <stdint.h>
// inst sequence type, used to order instructions in the ready list,
// if this rolls over the ready list order temporarily will get messed
// up, but execution will continue and complete correctly

Some files were not shown because too many files have changed in this diff Show more