Merge ARM into the head. ARM will compile but may not actually work.

This commit is contained in:
Gabe Black 2009-04-06 10:19:36 -07:00
commit d080581db1
1238 changed files with 77272 additions and 36447 deletions

View file

@ -16,3 +16,5 @@ b174ae14f007ba0c341f8df77d36f57f48369cc8 m5_2.0_beta2
91a9ac67662aa3a79315ade29b17a85961fecd88 m5_2.0_beta3 91a9ac67662aa3a79315ade29b17a85961fecd88 m5_2.0_beta3
dce5a8655829b7d2e24ce40cafc9c8873a71671f m5_2.0_beta5 dce5a8655829b7d2e24ce40cafc9c8873a71671f m5_2.0_beta5
1ac44b6c87ec71a8410c9a9c219269eca71f8077 m5_2.0_beta4 1ac44b6c87ec71a8410c9a9c219269eca71f8077 m5_2.0_beta4
60a931b03fb165807f02bcccc4f7d0fd705a67a9 copyright_update
d8b246a665c160a31751b4091f097022cde16dd7 m5_2.0_beta6

2
README
View file

@ -1,4 +1,4 @@
This is release 2.0_beta5 of the M5 simulator. This is release 2.0_beta6 of the M5 simulator.
For detailed information about building the simulator and getting For detailed information about building the simulator and getting
started please refer to http://www.m5sim.org. started please refer to http://www.m5sim.org.

View file

@ -1,13 +1,26 @@
October 6, 2008: m5_2.0_beta6
--------------------
New Features
1. Support for gcc 4.3
2. Core m5 code in libm5 for integration with other simulators
3. Preliminary support for X86 SE mode
4. Additional system calls emulated
5. m5term updated to work on OS X
6. Ability to disable listen sockets
7. Event queue performance improvements and rewrite
8. Better errors for unconnected memory ports
Bug fixes
1. ALPHA_SE O3 perlbmk benchmark
2. Translation bug where O3 could fetch from uncachable memory
3. Many minor bugs
Outstanding issues for 2.0 release: Outstanding issues for 2.0 release:
-------------------- --------------------
1. Fix O3 CPU bug in SE 40.perlbmk fails 1. Statistics cleanup
2. Fix O3 processing nacks/coherence messages 2. Improve regression system
3. Better statistics for the caches. 3. Testing
4. FS mode doesn't work under Cygwin 4. Validation
5. memtest regression crashes under Cygwin
6. Make repository public
7. Testing
8. Validation
March 1, 2008: m5_2.0_beta5 March 1, 2008: m5_2.0_beta5
-------------------- --------------------

File diff suppressed because it is too large Load diff

View file

@ -59,46 +59,46 @@ Benchmarks = {
'PovrayBench': [SysConfig('povray-bench.rcS', '512MB', 'povray.img')], 'PovrayBench': [SysConfig('povray-bench.rcS', '512MB', 'povray.img')],
'PovrayAutumn': [SysConfig('povray-autumn.rcS', '512MB', 'povray.img')], 'PovrayAutumn': [SysConfig('povray-autumn.rcS', '512MB', 'povray.img')],
'NetperfStream': [SysConfig('netperf-stream-client.rcS'), 'NetperfStream': [SysConfig('netperf-stream-client.rcS'),
SysConfig('netperf-server.rcS')], SysConfig('netperf-server.rcS')],
'NetperfStreamUdp': [SysConfig('netperf-stream-udp-client.rcS'), 'NetperfStreamUdp': [SysConfig('netperf-stream-udp-client.rcS'),
SysConfig('netperf-server.rcS')], SysConfig('netperf-server.rcS')],
'NetperfUdpLocal': [SysConfig('netperf-stream-udp-local.rcS')], 'NetperfUdpLocal': [SysConfig('netperf-stream-udp-local.rcS')],
'NetperfStreamNT': [SysConfig('netperf-stream-nt-client.rcS'), 'NetperfStreamNT': [SysConfig('netperf-stream-nt-client.rcS'),
SysConfig('netperf-server.rcS')], SysConfig('netperf-server.rcS')],
'NetperfMaerts': [SysConfig('netperf-maerts-client.rcS'), 'NetperfMaerts': [SysConfig('netperf-maerts-client.rcS'),
SysConfig('netperf-server.rcS')], SysConfig('netperf-server.rcS')],
'SurgeStandard': [SysConfig('surge-server.rcS', '512MB'), 'SurgeStandard': [SysConfig('surge-server.rcS', '512MB'),
SysConfig('surge-client.rcS', '256MB')], SysConfig('surge-client.rcS', '256MB')],
'SurgeSpecweb': [SysConfig('spec-surge-server.rcS', '512MB'), 'SurgeSpecweb': [SysConfig('spec-surge-server.rcS', '512MB'),
SysConfig('spec-surge-client.rcS', '256MB')], SysConfig('spec-surge-client.rcS', '256MB')],
'Nhfsstone': [SysConfig('nfs-server-nhfsstone.rcS', '512MB'), 'Nhfsstone': [SysConfig('nfs-server-nhfsstone.rcS', '512MB'),
SysConfig('nfs-client-nhfsstone.rcS')], SysConfig('nfs-client-nhfsstone.rcS')],
'Nfs': [SysConfig('nfs-server.rcS', '900MB'), 'Nfs': [SysConfig('nfs-server.rcS', '900MB'),
SysConfig('nfs-client-dbench.rcS')], SysConfig('nfs-client-dbench.rcS')],
'NfsTcp': [SysConfig('nfs-server.rcS', '900MB'), 'NfsTcp': [SysConfig('nfs-server.rcS', '900MB'),
SysConfig('nfs-client-tcp.rcS')], SysConfig('nfs-client-tcp.rcS')],
'IScsiInitiator': [SysConfig('iscsi-client.rcS', '512MB'), 'IScsiInitiator': [SysConfig('iscsi-client.rcS', '512MB'),
SysConfig('iscsi-server.rcS', '512MB')], SysConfig('iscsi-server.rcS', '512MB')],
'IScsiTarget': [SysConfig('iscsi-server.rcS', '512MB'), 'IScsiTarget': [SysConfig('iscsi-server.rcS', '512MB'),
SysConfig('iscsi-client.rcS', '512MB')], SysConfig('iscsi-client.rcS', '512MB')],
'Validation': [SysConfig('iscsi-server.rcS', '512MB'), 'Validation': [SysConfig('iscsi-server.rcS', '512MB'),
SysConfig('iscsi-client.rcS', '512MB')], SysConfig('iscsi-client.rcS', '512MB')],
'Ping': [SysConfig('ping-server.rcS',), 'Ping': [SysConfig('ping-server.rcS',),
SysConfig('ping-client.rcS')], SysConfig('ping-client.rcS')],
'ValAccDelay': [SysConfig('devtime.rcS', '512MB')], 'ValAccDelay': [SysConfig('devtime.rcS', '512MB')],
'ValAccDelay2': [SysConfig('devtimewmr.rcS', '512MB')], 'ValAccDelay2': [SysConfig('devtimewmr.rcS', '512MB')],
'ValMemLat': [SysConfig('micro_memlat.rcS', '512MB')], 'ValMemLat': [SysConfig('micro_memlat.rcS', '512MB')],
'ValMemLat2MB': [SysConfig('micro_memlat2mb.rcS', '512MB')], 'ValMemLat2MB': [SysConfig('micro_memlat2mb.rcS', '512MB')],
'ValMemLat8MB': [SysConfig('micro_memlat8mb.rcS', '512MB')], 'ValMemLat8MB': [SysConfig('micro_memlat8mb.rcS', '512MB')],
'ValMemLat': [SysConfig('micro_memlat8.rcS', '512MB')], 'ValMemLat': [SysConfig('micro_memlat8.rcS', '512MB')],
'ValTlbLat': [SysConfig('micro_tlblat.rcS', '512MB')], 'ValTlbLat': [SysConfig('micro_tlblat.rcS', '512MB')],
'ValSysLat': [SysConfig('micro_syscall.rcS', '512MB')], 'ValSysLat': [SysConfig('micro_syscall.rcS', '512MB')],
'ValCtxLat': [SysConfig('micro_ctx.rcS', '512MB')], 'ValCtxLat': [SysConfig('micro_ctx.rcS', '512MB')],
'ValStream': [SysConfig('micro_stream.rcS', '512MB')], 'ValStream': [SysConfig('micro_stream.rcS', '512MB')],
'ValStreamScale': [SysConfig('micro_streamscale.rcS', '512MB')], 'ValStreamScale': [SysConfig('micro_streamscale.rcS', '512MB')],
'ValStreamCopy': [SysConfig('micro_streamcopy.rcS', '512MB')], 'ValStreamCopy': [SysConfig('micro_streamcopy.rcS', '512MB')],
'MutexTest': [SysConfig('mutex-test.rcS', '128MB')], 'MutexTest': [SysConfig('mutex-test.rcS', '128MB')],

View file

@ -68,7 +68,7 @@ def makeLinuxAlphaSystem(mem_mode, mdesc = None):
read_only = True)) read_only = True))
self.intrctrl = IntrControl() self.intrctrl = IntrControl()
self.mem_mode = mem_mode self.mem_mode = mem_mode
self.sim_console = SimConsole() self.terminal = Terminal()
self.kernel = binary('vmlinux') self.kernel = binary('vmlinux')
self.pal = binary('ts_osfpal') self.pal = binary('ts_osfpal')
self.console = binary('console') self.console = binary('console')
@ -148,7 +148,7 @@ def makeLinuxMipsSystem(mem_mode, mdesc = None):
read_only = True)) read_only = True))
self.intrctrl = IntrControl() self.intrctrl = IntrControl()
self.mem_mode = mem_mode self.mem_mode = mem_mode
self.sim_console = SimConsole() self.terminal = Terminal()
self.kernel = binary('mips/vmlinux') self.kernel = binary('mips/vmlinux')
self.console = binary('mips/console') self.console = binary('mips/console')
self.boot_osflags = 'root=/dev/hda1 console=ttyS0' self.boot_osflags = 'root=/dev/hda1 console=ttyS0'
@ -159,11 +159,14 @@ def x86IOAddress(port):
IO_address_space_base = 0x8000000000000000 IO_address_space_base = 0x8000000000000000
return IO_address_space_base + port; return IO_address_space_base + port;
def makeLinuxX86System(mem_mode, mdesc = None): def makeX86System(mem_mode, mdesc = None, self = None):
self = LinuxX86System() if self == None:
self = X86System()
if not mdesc: if not mdesc:
# generic system # generic system
mdesc = SysConfig() mdesc = SysConfig()
mdesc.diskname = 'x86root.img'
self.readfile = mdesc.script() self.readfile = mdesc.script()
# Physical memory # Physical memory
@ -177,22 +180,168 @@ def makeLinuxX86System(mem_mode, mdesc = None):
self.bridge.side_a = self.iobus.port self.bridge.side_a = self.iobus.port
self.bridge.side_b = self.membus.port self.bridge.side_b = self.membus.port
# Serial port and console
self.console = SimConsole()
self.com_1 = Uart8250()
self.com_1.pio_addr = x86IOAddress(0x3f8)
self.com_1.pio = self.iobus.port
self.com_1.sim_console = self.console
# Command line
self.boot_osflags = 'earlyprintk=ttyS0'
# Platform # Platform
self.opteron = Opteron() self.pc = Pc()
self.opteron.attachIO(self.iobus) self.pc.attachIO(self.iobus)
self.intrctrl = IntrControl() self.intrctrl = IntrControl()
# Disks
disk0 = CowIdeDisk(driveID='master')
disk2 = CowIdeDisk(driveID='master')
disk0.childImage(mdesc.disk())
disk2.childImage(disk('linux-bigswap2.img'))
self.pc.south_bridge.ide.disks = [disk0, disk2]
# Add in a Bios information structure.
structures = [X86SMBiosBiosInformation()]
self.smbios_table.structures = structures
# Set up the Intel MP table
bp = X86IntelMPProcessor(
local_apic_id = 0,
local_apic_version = 0x14,
enable = True,
bootstrap = True)
self.intel_mp_table.add_entry(bp)
io_apic = X86IntelMPIOAPIC(
id = 1,
version = 0x11,
enable = True,
address = 0xfec00000)
self.intel_mp_table.add_entry(io_apic)
isa_bus = X86IntelMPBus(bus_id = 0, bus_type='ISA')
self.intel_mp_table.add_entry(isa_bus)
pci_bus = X86IntelMPBus(bus_id = 1, bus_type='PCI')
self.intel_mp_table.add_entry(pci_bus)
connect_busses = X86IntelMPBusHierarchy(bus_id=0,
subtractive_decode=True, parent_bus=1)
self.intel_mp_table.add_entry(connect_busses)
pci_dev4_inta = X86IntelMPIOIntAssignment(
interrupt_type = 'INT',
polarity = 'ConformPolarity',
trigger = 'ConformTrigger',
source_bus_id = 1,
source_bus_irq = 0 + (4 << 2),
dest_io_apic_id = 1,
dest_io_apic_intin = 16)
assign_8259_0_to_apic = X86IntelMPIOIntAssignment(
interrupt_type = 'ExtInt',
polarity = 'ConformPolarity',
trigger = 'ConformTrigger',
source_bus_id = 0,
source_bus_irq = 0,
dest_io_apic_id = 1,
dest_io_apic_intin = 0)
self.intel_mp_table.add_entry(assign_8259_0_to_apic)
assign_0_to_apic = X86IntelMPIOIntAssignment(
interrupt_type = 'INT',
polarity = 'ConformPolarity',
trigger = 'ConformTrigger',
source_bus_id = 0,
source_bus_irq = 0,
dest_io_apic_id = 1,
dest_io_apic_intin = 2)
self.intel_mp_table.add_entry(assign_0_to_apic)
assign_8259_1_to_apic = X86IntelMPIOIntAssignment(
interrupt_type = 'ExtInt',
polarity = 'ConformPolarity',
trigger = 'ConformTrigger',
source_bus_id = 0,
source_bus_irq = 1,
dest_io_apic_id = 1,
dest_io_apic_intin = 0)
self.intel_mp_table.add_entry(assign_8259_1_to_apic)
assign_1_to_apic = X86IntelMPIOIntAssignment(
interrupt_type = 'INT',
polarity = 'ConformPolarity',
trigger = 'ConformTrigger',
source_bus_id = 0,
source_bus_irq = 1,
dest_io_apic_id = 1,
dest_io_apic_intin = 1)
self.intel_mp_table.add_entry(assign_1_to_apic)
assign_8259_4_to_apic = X86IntelMPIOIntAssignment(
interrupt_type = 'ExtInt',
polarity = 'ConformPolarity',
trigger = 'ConformTrigger',
source_bus_id = 0,
source_bus_irq = 4,
dest_io_apic_id = 1,
dest_io_apic_intin = 0)
self.intel_mp_table.add_entry(assign_8259_4_to_apic)
assign_4_to_apic = X86IntelMPIOIntAssignment(
interrupt_type = 'INT',
polarity = 'ConformPolarity',
trigger = 'ConformTrigger',
source_bus_id = 0,
source_bus_irq = 4,
dest_io_apic_id = 1,
dest_io_apic_intin = 4)
self.intel_mp_table.add_entry(assign_4_to_apic)
assign_8259_12_to_apic = X86IntelMPIOIntAssignment(
interrupt_type = 'ExtInt',
polarity = 'ConformPolarity',
trigger = 'ConformTrigger',
source_bus_id = 0,
source_bus_irq = 12,
dest_io_apic_id = 1,
dest_io_apic_intin = 0)
self.intel_mp_table.add_entry(assign_8259_12_to_apic)
assign_12_to_apic = X86IntelMPIOIntAssignment(
interrupt_type = 'INT',
polarity = 'ConformPolarity',
trigger = 'ConformTrigger',
source_bus_id = 0,
source_bus_irq = 12,
dest_io_apic_id = 1,
dest_io_apic_intin = 12)
self.intel_mp_table.add_entry(assign_12_to_apic)
assign_8259_14_to_apic = X86IntelMPIOIntAssignment(
interrupt_type = 'ExtInt',
polarity = 'ConformPolarity',
trigger = 'ConformTrigger',
source_bus_id = 0,
source_bus_irq = 14,
dest_io_apic_id = 1,
dest_io_apic_intin = 0)
self.intel_mp_table.add_entry(assign_8259_14_to_apic)
assign_14_to_apic = X86IntelMPIOIntAssignment(
interrupt_type = 'INT',
polarity = 'ConformPolarity',
trigger = 'ConformTrigger',
source_bus_id = 0,
source_bus_irq = 14,
dest_io_apic_id = 1,
dest_io_apic_intin = 14)
self.intel_mp_table.add_entry(assign_14_to_apic)
def makeLinuxX86System(mem_mode, mdesc = None):
self = LinuxX86System()
# Build up a generic x86 system and then specialize it for Linux
makeX86System(mem_mode, mdesc, self)
# We assume below that there's at least 1MB of memory. We'll require 2
# just to avoid corner cases.
assert(self.physmem.range.second >= 0x200000)
# Mark the first megabyte of memory as reserved
self.e820_table.entries.append(X86E820Entry(
addr = 0,
size = '1MB',
range_type = 2))
# Mark the rest as available
self.e820_table.entries.append(X86E820Entry(
addr = 0x100000,
size = '%dB' % (self.physmem.range.second - 0x100000 - 1),
range_type = 1))
# Command line
self.boot_osflags = 'earlyprintk=ttyS0 console=ttyS0 lpj=7999923 ' + \
'root=/dev/hda1'
return self return self

View file

@ -29,6 +29,7 @@
# system options # system options
parser.add_option("-d", "--detailed", action="store_true") parser.add_option("-d", "--detailed", action="store_true")
parser.add_option("-t", "--timing", action="store_true") parser.add_option("-t", "--timing", action="store_true")
parser.add_option("--inorder", action="store_true")
parser.add_option("-n", "--num-cpus", type="int", default=1) parser.add_option("-n", "--num-cpus", type="int", default=1)
parser.add_option("--caches", action="store_true") parser.add_option("--caches", action="store_true")
parser.add_option("--l2cache", action="store_true") parser.add_option("--l2cache", action="store_true")

View file

@ -43,6 +43,11 @@ def setCPUClass(options):
print "O3 CPU must be used with caches" print "O3 CPU must be used with caches"
sys.exit(1) sys.exit(1)
class TmpClass(DerivO3CPU): pass class TmpClass(DerivO3CPU): pass
elif options.inorder:
if not options.caches:
print "InOrder CPU must be used with caches"
sys.exit(1)
class TmpClass(InOrderCPU): pass
else: else:
class TmpClass(AtomicSimpleCPU): pass class TmpClass(AtomicSimpleCPU): pass
atomic = True atomic = True
@ -78,10 +83,10 @@ def run(options, root, testsys, cpu_class):
cptdir = getcwd() cptdir = getcwd()
if options.fast_forward and options.checkpoint_restore != None: if options.fast_forward and options.checkpoint_restore != None:
m5.panic("Error: Can't specify both --fast-forward and --checkpoint-restore") m5.fatal("Error: Can't specify both --fast-forward and --checkpoint-restore")
if options.standard_switch and not options.caches: if options.standard_switch and not options.caches:
m5.panic("Error: Must specify --caches when using --standard-switch") m5.fatal("Error: Must specify --caches when using --standard-switch")
np = options.num_cpus np = options.num_cpus
max_checkpoints = options.max_checkpoints max_checkpoints = options.max_checkpoints
@ -128,8 +133,8 @@ def run(options, root, testsys, cpu_class):
testsys.cpu[i].max_insts_any_thread = int(options.fast_forward) testsys.cpu[i].max_insts_any_thread = int(options.fast_forward)
# Fast forward to a simpoint (warning: time consuming) # Fast forward to a simpoint (warning: time consuming)
elif options.simpoint: elif options.simpoint:
if testsys.cpu[i].workload[0].simpoint == None: if testsys.cpu[i].workload[0].simpoint == 0:
m5.panic('simpoint not found') m5.fatal('simpoint not found')
testsys.cpu[i].max_insts_any_thread = \ testsys.cpu[i].max_insts_any_thread = \
testsys.cpu[i].workload[0].simpoint testsys.cpu[i].workload[0].simpoint
# No distance specified, just switch # No distance specified, just switch
@ -162,8 +167,8 @@ def run(options, root, testsys, cpu_class):
# Set an instruction break point # Set an instruction break point
if options.simpoint: if options.simpoint:
for i in xrange(np): for i in xrange(np):
if testsys.cpu[i].workload[0].simpoint == None: if testsys.cpu[i].workload[0].simpoint == 0:
m5.panic('no simpoint for testsys.cpu[%d].workload[0]' % i) m5.fatal('no simpoint for testsys.cpu[%d].workload[0]', i)
checkpoint_inst = int(testsys.cpu[i].workload[0].simpoint) + offset checkpoint_inst = int(testsys.cpu[i].workload[0].simpoint) + offset
testsys.cpu[i].max_insts_any_thread = checkpoint_inst testsys.cpu[i].max_insts_any_thread = checkpoint_inst
# used for output below # used for output below
@ -183,13 +188,13 @@ def run(options, root, testsys, cpu_class):
import re import re
if not isdir(cptdir): if not isdir(cptdir):
m5.panic("checkpoint dir %s does not exist!" % cptdir) m5.fatal("checkpoint dir %s does not exist!", cptdir)
if options.at_instruction: if options.at_instruction:
checkpoint_dir = joinpath(cptdir, "cpt.%s.%s" % \ checkpoint_dir = joinpath(cptdir, "cpt.%s.%s" % \
(options.bench, options.checkpoint_restore)) (options.bench, options.checkpoint_restore))
if not exists(checkpoint_dir): if not exists(checkpoint_dir):
m5.panic("Unable to find checkpoint directory %s" % \ m5.fatal("Unable to find checkpoint directory %s",
checkpoint_dir) checkpoint_dir)
print "Restoring checkpoint ..." print "Restoring checkpoint ..."
@ -197,8 +202,8 @@ def run(options, root, testsys, cpu_class):
print "Done." print "Done."
elif options.simpoint: elif options.simpoint:
# assume workload 0 has the simpoint # assume workload 0 has the simpoint
if testsys.cpu[0].workload[0].simpoint == None: if testsys.cpu[0].workload[0].simpoint == 0:
m5.panic('Unable to find simpoint') m5.fatal('Unable to find simpoint')
options.checkpoint_restore += \ options.checkpoint_restore += \
int(testsys.cpu[0].workload[0].simpoint) int(testsys.cpu[0].workload[0].simpoint)
@ -206,8 +211,8 @@ def run(options, root, testsys, cpu_class):
checkpoint_dir = joinpath(cptdir, "cpt.%s.%d" % \ checkpoint_dir = joinpath(cptdir, "cpt.%s.%d" % \
(options.bench, options.checkpoint_restore)) (options.bench, options.checkpoint_restore))
if not exists(checkpoint_dir): if not exists(checkpoint_dir):
m5.panic("Unable to find checkpoint directory %s.%s" % \ m5.fatal("Unable to find checkpoint directory %s.%s",
(options.bench, options.checkpoint_restore)) options.bench, options.checkpoint_restore)
print "Restoring checkpoint ..." print "Restoring checkpoint ..."
m5.restoreCheckpoint(root,checkpoint_dir) m5.restoreCheckpoint(root,checkpoint_dir)
@ -226,7 +231,7 @@ def run(options, root, testsys, cpu_class):
cpt_num = options.checkpoint_restore cpt_num = options.checkpoint_restore
if cpt_num > len(cpts): if cpt_num > len(cpts):
m5.panic('Checkpoint %d not found' % cpt_num) m5.fatal('Checkpoint %d not found', cpt_num)
## Adjust max tick based on our starting tick ## Adjust max tick based on our starting tick
maxtick = maxtick - int(cpts[cpt_num - 1]) maxtick = maxtick - int(cpts[cpt_num - 1])

View file

@ -140,7 +140,8 @@ class Benchmark(object):
process_args['input'] = self.stdin process_args['input'] = self.stdin
if self.stdout: if self.stdout:
process_args['output'] = self.stdout process_args['output'] = self.stdout
process_args['simpoint'] = self.simpoint if self.simpoint:
process_args['simpoint'] = self.simpoint
# explicit keywords override defaults # explicit keywords override defaults
process_args.update(kwargs) process_args.update(kwargs)

View file

@ -29,6 +29,10 @@
import optparse, os, sys import optparse, os, sys
import m5 import m5
if not m5.build_env['FULL_SYSTEM']:
m5.fatal("This script requires full-system mode (*_FS).")
from m5.objects import * from m5.objects import *
m5.AddToPath('../common') m5.AddToPath('../common')
from FSConfig import * from FSConfig import *
@ -37,9 +41,6 @@ from Benchmarks import *
import Simulation import Simulation
from Caches import * from Caches import *
if not m5.build_env['FULL_SYSTEM']:
m5.panic("This script requires full-system mode (ALPHA_FS).")
# Get paths we might need. It's expected this file is in m5/configs/example. # Get paths we might need. It's expected this file is in m5/configs/example.
config_path = os.path.dirname(os.path.abspath(__file__)) config_path = os.path.dirname(os.path.abspath(__file__))
config_root = os.path.dirname(config_path) config_root = os.path.dirname(config_path)
@ -104,7 +105,7 @@ elif m5.build_env['TARGET_ISA'] == "sparc":
elif m5.build_env['TARGET_ISA'] == "x86": elif m5.build_env['TARGET_ISA'] == "x86":
test_sys = makeLinuxX86System(test_mem_mode, bm[0]) test_sys = makeLinuxX86System(test_mem_mode, bm[0])
else: else:
m5.panic("incapable of building non-alpha or non-sparc full system!") m5.fatal("incapable of building non-alpha or non-sparc full system!")
if options.kernel is not None: if options.kernel is not None:
test_sys.kernel = binary(options.kernel) test_sys.kernel = binary(options.kernel)

View file

@ -31,8 +31,13 @@
# "m5 test.py" # "m5 test.py"
import m5 import m5
if m5.build_env['FULL_SYSTEM']:
m5.fatal("This script requires syscall emulation mode (*_SE).")
from m5.objects import * from m5.objects import *
import os, optparse, sys import os, optparse, sys
from os.path import join as joinpath
m5.AddToPath('../common') m5.AddToPath('../common')
import Simulation import Simulation
from Caches import * from Caches import *
@ -47,13 +52,13 @@ parser = optparse.OptionParser()
# Benchmark options # Benchmark options
parser.add_option("-c", "--cmd", parser.add_option("-c", "--cmd",
default=os.path.join(m5_root, "tests/test-progs/hello/bin/alpha/linux/hello"), default=joinpath(m5_root, "tests/test-progs/hello/bin/alpha/linux/hello"),
help="The binary to run in syscall emulation mode.") help="The binary to run in syscall emulation mode.")
parser.add_option("-o", "--options", default="", parser.add_option("-o", "--options", default="",
help="The options to pass to the binary, use \" \" around the entire\ help='The options to pass to the binary, use " " around the entire string')
string.") parser.add_option("-i", "--input", default="", help="Read stdin from a file.")
parser.add_option("-i", "--input", default="", parser.add_option("--output", default="", help="Redirect stdout to a file.")
help="A file of input to give to the binary.") parser.add_option("--errout", default="", help="Redirect stderr to a file.")
execfile(os.path.join(config_root, "common", "Options.py")) execfile(os.path.join(config_root, "common", "Options.py"))
@ -81,6 +86,10 @@ else:
if options.input != "": if options.input != "":
process.input = options.input process.input = options.input
if options.output != "":
process.output = options.output
if options.errout != "":
process.errout = options.errout
if options.detailed: if options.detailed:
#check for SMT workload #check for SMT workload
@ -89,9 +98,15 @@ if options.detailed:
process = [] process = []
smt_idx = 0 smt_idx = 0
inputs = [] inputs = []
outputs = []
errouts = []
if options.input != "": if options.input != "":
inputs = options.input.split(';') inputs = options.input.split(';')
if options.output != "":
outputs = options.output.split(';')
if options.errout != "":
errouts = options.errout.split(';')
for wrkld in workloads: for wrkld in workloads:
smt_process = LiveProcess() smt_process = LiveProcess()
@ -99,6 +114,10 @@ if options.detailed:
smt_process.cmd = wrkld + " " + options.options smt_process.cmd = wrkld + " " + options.options
if inputs and inputs[smt_idx]: if inputs and inputs[smt_idx]:
smt_process.input = inputs[smt_idx] smt_process.input = inputs[smt_idx]
if outputs and outputs[smt_idx]:
smt_process.output = outputs[smt_idx]
if errouts and errouts[smt_idx]:
smt_process.errout = errouts[smt_idx]
process += [smt_process, ] process += [smt_process, ]
smt_idx += 1 smt_idx += 1

504
ext/gzstream/LICENSE Normal file
View file

@ -0,0 +1,504 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

38
ext/gzstream/SConscript Normal file
View file

@ -0,0 +1,38 @@
# -*- mode:python -*-
# 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
Import('env')
env.Library('gzstream', [File('gzstream.cc')])
env.Append(CPPPATH=Dir('.'))
env.Append(LIBS=['gzstream'])
env.Append(LIBPATH=[Dir('.')])

1
ext/gzstream/VERSION Normal file
View file

@ -0,0 +1 @@
1.5 (08 Jan 2003)

165
ext/gzstream/gzstream.cc Normal file
View file

@ -0,0 +1,165 @@
// ============================================================================
// gzstream, C++ iostream classes wrapping the zlib compression library.
// Copyright (C) 2001 Deepak Bandyopadhyay, Lutz Kettner
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// ============================================================================
//
// File : gzstream.C
// Revision : $Revision: 1.7 $
// Revision_date : $Date: 2003/01/08 14:41:27 $
// Author(s) : Deepak Bandyopadhyay, Lutz Kettner
//
// Standard streambuf implementation following Nicolai Josuttis, "The
// Standard C++ Library".
// ============================================================================
#include <gzstream.hh>
#include <iostream>
#include <string.h> // for memcpy
#ifdef GZSTREAM_NAMESPACE
namespace GZSTREAM_NAMESPACE {
#endif
// ----------------------------------------------------------------------------
// Internal classes to implement gzstream. See header file for user classes.
// ----------------------------------------------------------------------------
// --------------------------------------
// class gzstreambuf:
// --------------------------------------
gzstreambuf* gzstreambuf::open( const char* name, int open_mode) {
if ( is_open())
return (gzstreambuf*)0;
mode = open_mode;
// no append nor read/write mode
if ((mode & std::ios::ate) || (mode & std::ios::app)
|| ((mode & std::ios::in) && (mode & std::ios::out)))
return (gzstreambuf*)0;
char fmode[10];
char* fmodeptr = fmode;
if ( mode & std::ios::in)
*fmodeptr++ = 'r';
else if ( mode & std::ios::out)
*fmodeptr++ = 'w';
*fmodeptr++ = 'b';
*fmodeptr = '\0';
file = gzopen( name, fmode);
if (file == 0)
return (gzstreambuf*)0;
opened = 1;
return this;
}
gzstreambuf * gzstreambuf::close() {
if ( is_open()) {
sync();
opened = 0;
if ( gzclose( file) == Z_OK)
return this;
}
return (gzstreambuf*)0;
}
int gzstreambuf::underflow() { // used for input buffer only
if ( gptr() && ( gptr() < egptr()))
return * reinterpret_cast<unsigned char *>( gptr());
if ( ! (mode & std::ios::in) || ! opened)
return EOF;
// Josuttis' implementation of inbuf
int n_putback = gptr() - eback();
if ( n_putback > 4)
n_putback = 4;
memcpy( buffer + (4 - n_putback), gptr() - n_putback, n_putback);
int num = gzread( file, buffer+4, bufferSize-4);
if (num <= 0) // ERROR or EOF
return EOF;
// reset buffer pointers
setg( buffer + (4 - n_putback), // beginning of putback area
buffer + 4, // read position
buffer + 4 + num); // end of buffer
// return next character
return *reinterpret_cast<unsigned char *>(gptr());
}
int gzstreambuf::flush_buffer() {
// Separate the writing of the buffer from overflow() and
// sync() operation.
int w = pptr() - pbase();
if ( gzwrite( file, pbase(), w) != w)
return EOF;
pbump( -w);
return w;
}
int gzstreambuf::overflow( int c) { // used for output buffer only
if ( ! ( mode & std::ios::out) || ! opened)
return EOF;
if (c != EOF) {
*pptr() = c;
pbump(1);
}
if ( flush_buffer() == EOF)
return EOF;
return c;
}
int gzstreambuf::sync() {
// Changed to use flush_buffer() instead of overflow( EOF)
// which caused improper behavior with std::endl and flush(),
// bug reported by Vincent Ricard.
if ( pptr() && pptr() > pbase()) {
if ( flush_buffer() == EOF)
return -1;
}
return 0;
}
// --------------------------------------
// class gzstreambase:
// --------------------------------------
gzstreambase::gzstreambase( const char* name, int mode) {
init( &buf);
open( name, mode);
}
gzstreambase::~gzstreambase() {
buf.close();
}
void gzstreambase::open( const char* name, int open_mode) {
if ( ! buf.open( name, open_mode))
clear( rdstate() | std::ios::badbit);
}
void gzstreambase::close() {
if ( buf.is_open())
if ( ! buf.close())
clear( rdstate() | std::ios::badbit);
}
#ifdef GZSTREAM_NAMESPACE
} // namespace GZSTREAM_NAMESPACE
#endif
// ============================================================================
// EOF //

122
ext/gzstream/gzstream.hh Normal file
View file

@ -0,0 +1,122 @@
// ============================================================================
// gzstream, C++ iostream classes wrapping the zlib compression library.
// Copyright (C) 2001 Deepak Bandyopadhyay, Lutz Kettner
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// ============================================================================
//
// File : gzstream.h
// Revision : $Revision: 1.5 $
// Revision_date : $Date: 2002/04/26 23:30:15 $
// Author(s) : Deepak Bandyopadhyay, Lutz Kettner
//
// Standard streambuf implementation following Nicolai Josuttis, "The
// Standard C++ Library".
// ============================================================================
#ifndef GZSTREAM_H
#define GZSTREAM_H 1
// standard C++ with new header file names and std:: namespace
#include <iostream>
#include <fstream>
#include <zlib.h>
#ifdef GZSTREAM_NAMESPACE
namespace GZSTREAM_NAMESPACE {
#endif
// ----------------------------------------------------------------------------
// Internal classes to implement gzstream. See below for user classes.
// ----------------------------------------------------------------------------
class gzstreambuf : public std::streambuf {
private:
static const int bufferSize = 47+256; // size of data buff
// totals 512 bytes under g++ for igzstream at the end.
gzFile file; // file handle for compressed file
char buffer[bufferSize]; // data buffer
char opened; // open/close state of stream
int mode; // I/O mode
int flush_buffer();
public:
gzstreambuf() : opened(0) {
setp( buffer, buffer + (bufferSize-1));
setg( buffer + 4, // beginning of putback area
buffer + 4, // read position
buffer + 4); // end position
// ASSERT: both input & output capabilities will not be used together
}
int is_open() { return opened; }
gzstreambuf* open( const char* name, int open_mode);
gzstreambuf* close();
~gzstreambuf() { close(); }
virtual int overflow( int c = EOF);
virtual int underflow();
virtual int sync();
};
class gzstreambase : virtual public std::ios {
protected:
gzstreambuf buf;
public:
gzstreambase() { init(&buf); }
gzstreambase( const char* name, int open_mode);
~gzstreambase();
int is_open() { return buf.is_open(); }
void open( const char* name, int open_mode);
void close();
gzstreambuf* rdbuf() { return &buf; }
};
// ----------------------------------------------------------------------------
// User classes. Use igzstream and ogzstream analogously to ifstream and
// ofstream respectively. They read and write files based on the gz*
// function interface of the zlib. Files are compatible with gzip compression.
// ----------------------------------------------------------------------------
class igzstream : public gzstreambase, public std::istream {
public:
igzstream() : std::istream( &buf) {}
igzstream( const char* name, int open_mode = std::ios::in)
: gzstreambase( name, open_mode | std::ios::in), std::istream( &buf) {}
gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); }
void open( const char* name, int open_mode = std::ios::in) {
gzstreambase::open( name, open_mode);
}
};
class ogzstream : public gzstreambase, public std::ostream {
public:
ogzstream() : std::ostream( &buf) {}
ogzstream( const char* name, int mode = std::ios::out)
: gzstreambase( name, mode | std::ios::out), std::ostream( &buf) {}
gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); }
void open( const char* name, int open_mode = std::ios::out) {
gzstreambase::open( name, open_mode);
}
};
#ifdef GZSTREAM_NAMESPACE
} // namespace GZSTREAM_NAMESPACE
#endif
#endif // GZSTREAM_H
// ============================================================================
// EOF //

View file

@ -87,16 +87,13 @@ ElfFile('libelf_convert.c')
ElfFile('libelf_fsize.c') ElfFile('libelf_fsize.c')
ElfFile('libelf_msize.c') ElfFile('libelf_msize.c')
m4env = Environment(ENV=os.environ) m4env = env.Clone()
if env['GCC']:
if env.get('CC'): major,minor,dot = [ int(x) for x in env['CXXVERSION'].split('.')]
m4env['CC'] = env['CC'] if major >= 4:
if env.get('CXX'): m4env.Append(CCFLAGS=['-Wno-pointer-sign'])
m4env['CXX'] = env['CXX'] m4env.Append(CCFLAGS=['-Wno-implicit'])
del m4env['CPPPATH']
if env.get('OSX64bit'):
m4env.Append(CFLAGS='-arch x86_64')
m4env.Append(LINKFLAGS='-arch x86_64')
# If we have gm4 use it # If we have gm4 use it
if m4env.Detect('gm4'): if m4env.Detect('gm4'):
@ -117,7 +114,10 @@ m4env.M4(target=File('libelf_fsize.c'),
source=[File('elf_types.m4'), File('libelf_fsize.m4')]) source=[File('elf_types.m4'), File('libelf_fsize.m4')])
m4env.M4(target=File('libelf_msize.c'), m4env.M4(target=File('libelf_msize.c'),
source=[File('elf_types.m4'), File('libelf_msize.m4')]) source=[File('elf_types.m4'), File('libelf_msize.m4')])
m4env.Library('elf', elf_files)
# Build libelf as a static library with PIC code so it can be linked
# into either m5 or the library
m4env.Library('elf', [m4env.SharedObject(f) for f in elf_files])
env.Append(CPPPATH=Dir('.')) env.Append(CPPPATH=Dir('.'))
env.Append(LIBS=['elf']) env.Append(LIBS=['elf'])

File diff suppressed because it is too large Load diff

View file

@ -49,13 +49,13 @@ isa_switch_hdrs = Split('''
isa_traits.hh isa_traits.hh
kernel_stats.hh kernel_stats.hh
locked_mem.hh locked_mem.hh
microcode_rom.hh
mmaped_ipr.hh mmaped_ipr.hh
process.hh process.hh
predecoder.hh predecoder.hh
regfile.hh regfile.hh
remote_gdb.hh remote_gdb.hh
stacktrace.hh stacktrace.hh
syscallreturn.hh
tlb.hh tlb.hh
types.hh types.hh
utility.hh utility.hh
@ -125,3 +125,8 @@ else:
emitter = isa_desc_emitter) emitter = isa_desc_emitter)
env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder }) env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder })
TraceFlag('IntRegs')
TraceFlag('FloatRegs')
TraceFlag('MiscRegs')
CompoundFlag('Registers', [ 'IntRegs', 'FloatRegs', 'MiscRegs' ])

View file

@ -0,0 +1,33 @@
# Copyright (c) 2008 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
from m5.SimObject import SimObject
class AlphaInterrupts(SimObject):
type = 'AlphaInterrupts'
cxx_class = 'AlphaISA::Interrupts'

View file

@ -28,21 +28,20 @@
from m5.SimObject import SimObject from m5.SimObject import SimObject
from m5.params import * from m5.params import *
class AlphaTLB(SimObject):
from BaseTLB import BaseTLB
class AlphaTLB(BaseTLB):
type = 'AlphaTLB' type = 'AlphaTLB'
abstract = True abstract = True
size = Param.Int("TLB size") size = Param.Int("TLB size")
class AlphaDTB(AlphaTLB): class AlphaDTB(AlphaTLB):
type = 'AlphaDTB' type = 'AlphaDTB'
cxx_namespace = 'AlphaISA' cxx_class = 'AlphaISA::DTB'
cxx_class = 'DTB'
size = 64 size = 64
class AlphaITB(AlphaTLB): class AlphaITB(AlphaTLB):
type = 'AlphaITB' type = 'AlphaITB'
cxx_namespace = 'AlphaISA' cxx_class = 'AlphaISA::ITB'
cxx_class = 'ITB'
size = 48 size = 48

View file

@ -47,9 +47,11 @@ if env['TARGET_ISA'] == 'alpha':
SimObject('AlphaTLB.py') SimObject('AlphaTLB.py')
if env['FULL_SYSTEM']: if env['FULL_SYSTEM']:
SimObject('AlphaInterrupts.py')
SimObject('AlphaSystem.py') SimObject('AlphaSystem.py')
Source('idle_event.cc') Source('idle_event.cc')
Source('interrupts.cc')
Source('kernel_stats.cc') Source('kernel_stats.cc')
Source('osfpal.cc') Source('osfpal.cc')
Source('stacktrace.cc') Source('stacktrace.cc')

View file

@ -33,5 +33,5 @@ Import('*')
all_isa_list.append('alpha') all_isa_list.append('alpha')
# Alpha can be compiled with Turbolaser support instead of Tsunami # Alpha can be compiled with Turbolaser support instead of Tsunami
sticky_opts.Add(BoolOption('ALPHA_TLASER', sticky_vars.Add(BoolVariable('ALPHA_TLASER',
'Model Alpha TurboLaser platform (vs. Tsunami)', False)) 'Model Alpha TurboLaser platform (vs. Tsunami)', False))

View file

@ -36,35 +36,35 @@
/// Funky Alpha 64-bit a.out header used for PAL code. /// Funky Alpha 64-bit a.out header used for PAL code.
/// ///
struct aout_exechdr { struct aout_exechdr {
uint16_t magic; ///< magic number uint16_t magic; ///< magic number
uint16_t vstamp; ///< version stamp? uint16_t vstamp; ///< version stamp?
uint16_t bldrev; ///< ??? uint16_t bldrev; ///< ???
uint16_t padcell; ///< padding uint16_t padcell; ///< padding
uint64_t tsize; ///< text segment size uint64_t tsize; ///< text segment size
uint64_t dsize; ///< data segment size uint64_t dsize; ///< data segment size
uint64_t bsize; ///< bss segment size uint64_t bsize; ///< bss segment size
uint64_t entry; ///< entry point uint64_t entry; ///< entry point
uint64_t text_start; ///< text base address uint64_t text_start; ///< text base address
uint64_t data_start; ///< data base address uint64_t data_start; ///< data base address
uint64_t bss_start; ///< bss base address uint64_t bss_start; ///< bss base address
uint32_t gprmask; ///< GPR mask (unused, AFAIK) uint32_t gprmask; ///< GPR mask (unused, AFAIK)
uint32_t fprmask; ///< FPR mask (unused, AFAIK) uint32_t fprmask; ///< FPR mask (unused, AFAIK)
uint64_t gp_value; ///< global pointer reg value uint64_t gp_value; ///< global pointer reg value
}; };
#define AOUT_LDPGSZ 8192 #define AOUT_LDPGSZ 8192
#define N_GETMAGIC(ex) ((ex).magic) #define N_GETMAGIC(ex) ((ex).magic)
#define N_BADMAX #define N_BADMAX
#define N_TXTADDR(ex) ((ex).text_start) #define N_TXTADDR(ex) ((ex).text_start)
#define N_DATADDR(ex) ((ex).data_start) #define N_DATADDR(ex) ((ex).data_start)
#define N_BSSADDR(ex) ((ex).bss_start) #define N_BSSADDR(ex) ((ex).bss_start)
#define N_TXTOFF(ex) \ #define N_TXTOFF(ex) \
(N_GETMAGIC(ex) == ZMAGIC ? 0 : sizeof(struct aout_exechdr)) (N_GETMAGIC(ex) == ZMAGIC ? 0 : sizeof(struct aout_exechdr))
#define N_DATOFF(ex) N_ALIGN(ex, N_TXTOFF(ex) + (ex).tsize) #define N_DATOFF(ex) N_ALIGN(ex, N_TXTOFF(ex) + (ex).tsize)
#endif /* !__AOUT_MACHDEP_H__*/ #endif /* !__AOUT_MACHDEP_H__*/

View file

@ -35,32 +35,33 @@
#include "arch/alpha/osfpal.hh" #include "arch/alpha/osfpal.hh"
#include "arch/alpha/tlb.hh" #include "arch/alpha/tlb.hh"
#include "arch/alpha/kgdb.h" #include "arch/alpha/kgdb.h"
#include "base/cp_annotate.hh"
#include "base/debug.hh"
#include "base/remote_gdb.hh" #include "base/remote_gdb.hh"
#include "base/stats/events.hh" #include "base/stats/events.hh"
#include "config/full_system.hh" #include "config/full_system.hh"
#include "cpu/base.hh" #include "cpu/base.hh"
#include "cpu/simple_thread.hh" #include "cpu/simple_thread.hh"
#include "cpu/thread_context.hh" #include "cpu/thread_context.hh"
#include "sim/debug.hh"
#include "sim/sim_exit.hh" #include "sim/sim_exit.hh"
#if FULL_SYSTEM namespace AlphaISA {
using namespace EV5; #if FULL_SYSTEM
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// //
// Machine dependent functions // Machine dependent functions
// //
void void
AlphaISA::initCPU(ThreadContext *tc, int cpuId) initCPU(ThreadContext *tc, int cpuId)
{ {
initIPRs(tc, cpuId); initIPRs(tc, cpuId);
tc->setIntReg(16, cpuId); tc->setIntReg(16, cpuId);
tc->setIntReg(0, cpuId); tc->setIntReg(0, cpuId);
AlphaISA::AlphaFault *reset = new AlphaISA::ResetFault; AlphaFault *reset = new ResetFault;
tc->setPC(tc->readMiscRegNoEffect(IPR_PAL_BASE) + reset->vect()); tc->setPC(tc->readMiscRegNoEffect(IPR_PAL_BASE) + reset->vect());
tc->setNextPC(tc->readPC() + sizeof(MachInst)); tc->setNextPC(tc->readPC() + sizeof(MachInst));
@ -71,7 +72,7 @@ AlphaISA::initCPU(ThreadContext *tc, int cpuId)
template <class CPU> template <class CPU>
void void
AlphaISA::processInterrupts(CPU *cpu) processInterrupts(CPU *cpu)
{ {
//Check if there are any outstanding interrupts //Check if there are any outstanding interrupts
//Handle the interrupts //Handle the interrupts
@ -117,7 +118,7 @@ AlphaISA::processInterrupts(CPU *cpu)
template <class CPU> template <class CPU>
void void
AlphaISA::zeroRegisters(CPU *cpu) zeroRegisters(CPU *cpu)
{ {
// Insure ISA semantics // Insure ISA semantics
// (no longer very clean due to the change in setIntReg() in the // (no longer very clean due to the change in setIntReg() in the
@ -126,33 +127,16 @@ AlphaISA::zeroRegisters(CPU *cpu)
cpu->thread->setFloatReg(ZeroReg, 0.0); cpu->thread->setFloatReg(ZeroReg, 0.0);
} }
Fault int
SimpleThread::hwrei() MiscRegFile::getInstAsid()
{ {
if (!(readPC() & 0x3)) return ITB_ASN_ASN(ipr[IPR_ITB_ASN]);
return new UnimplementedOpcodeFault;
setNextPC(readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR));
if (!misspeculating()) {
if (kernelStats)
kernelStats->hwrei();
}
// FIXME: XXX check for interrupts? XXX
return NoFault;
} }
int int
AlphaISA::MiscRegFile::getInstAsid() MiscRegFile::getDataAsid()
{ {
return EV5::ITB_ASN_ASN(ipr[IPR_ITB_ASN]); return DTB_ASN_ASN(ipr[IPR_DTB_ASN]);
}
int
AlphaISA::MiscRegFile::getDataAsid()
{
return EV5::DTB_ASN_ASN(ipr[IPR_DTB_ASN]);
} }
#endif #endif
@ -162,90 +146,90 @@ AlphaISA::MiscRegFile::getDataAsid()
// //
// //
void void
AlphaISA::initIPRs(ThreadContext *tc, int cpuId) initIPRs(ThreadContext *tc, int cpuId)
{ {
for (int i = 0; i < NumInternalProcRegs; ++i) { for (int i = 0; i < NumInternalProcRegs; ++i) {
tc->setMiscRegNoEffect(i, 0); tc->setMiscRegNoEffect(i, 0);
} }
tc->setMiscRegNoEffect(IPR_PAL_BASE, EV5::PalBase); tc->setMiscRegNoEffect(IPR_PAL_BASE, PalBase);
tc->setMiscRegNoEffect(IPR_MCSR, 0x6); tc->setMiscRegNoEffect(IPR_MCSR, 0x6);
tc->setMiscRegNoEffect(IPR_PALtemp16, cpuId); tc->setMiscRegNoEffect(IPR_PALtemp16, cpuId);
} }
AlphaISA::MiscReg MiscReg
AlphaISA::MiscRegFile::readIpr(int idx, ThreadContext *tc) MiscRegFile::readIpr(int idx, ThreadContext *tc)
{ {
uint64_t retval = 0; // return value, default 0 uint64_t retval = 0; // return value, default 0
switch (idx) { switch (idx) {
case AlphaISA::IPR_PALtemp0: case IPR_PALtemp0:
case AlphaISA::IPR_PALtemp1: case IPR_PALtemp1:
case AlphaISA::IPR_PALtemp2: case IPR_PALtemp2:
case AlphaISA::IPR_PALtemp3: case IPR_PALtemp3:
case AlphaISA::IPR_PALtemp4: case IPR_PALtemp4:
case AlphaISA::IPR_PALtemp5: case IPR_PALtemp5:
case AlphaISA::IPR_PALtemp6: case IPR_PALtemp6:
case AlphaISA::IPR_PALtemp7: case IPR_PALtemp7:
case AlphaISA::IPR_PALtemp8: case IPR_PALtemp8:
case AlphaISA::IPR_PALtemp9: case IPR_PALtemp9:
case AlphaISA::IPR_PALtemp10: case IPR_PALtemp10:
case AlphaISA::IPR_PALtemp11: case IPR_PALtemp11:
case AlphaISA::IPR_PALtemp12: case IPR_PALtemp12:
case AlphaISA::IPR_PALtemp13: case IPR_PALtemp13:
case AlphaISA::IPR_PALtemp14: case IPR_PALtemp14:
case AlphaISA::IPR_PALtemp15: case IPR_PALtemp15:
case AlphaISA::IPR_PALtemp16: case IPR_PALtemp16:
case AlphaISA::IPR_PALtemp17: case IPR_PALtemp17:
case AlphaISA::IPR_PALtemp18: case IPR_PALtemp18:
case AlphaISA::IPR_PALtemp19: case IPR_PALtemp19:
case AlphaISA::IPR_PALtemp20: case IPR_PALtemp20:
case AlphaISA::IPR_PALtemp21: case IPR_PALtemp21:
case AlphaISA::IPR_PALtemp22: case IPR_PALtemp22:
case AlphaISA::IPR_PALtemp23: case IPR_PALtemp23:
case AlphaISA::IPR_PAL_BASE: case IPR_PAL_BASE:
case AlphaISA::IPR_IVPTBR: case IPR_IVPTBR:
case AlphaISA::IPR_DC_MODE: case IPR_DC_MODE:
case AlphaISA::IPR_MAF_MODE: case IPR_MAF_MODE:
case AlphaISA::IPR_ISR: case IPR_ISR:
case AlphaISA::IPR_EXC_ADDR: case IPR_EXC_ADDR:
case AlphaISA::IPR_IC_PERR_STAT: case IPR_IC_PERR_STAT:
case AlphaISA::IPR_DC_PERR_STAT: case IPR_DC_PERR_STAT:
case AlphaISA::IPR_MCSR: case IPR_MCSR:
case AlphaISA::IPR_ASTRR: case IPR_ASTRR:
case AlphaISA::IPR_ASTER: case IPR_ASTER:
case AlphaISA::IPR_SIRR: case IPR_SIRR:
case AlphaISA::IPR_ICSR: case IPR_ICSR:
case AlphaISA::IPR_ICM: case IPR_ICM:
case AlphaISA::IPR_DTB_CM: case IPR_DTB_CM:
case AlphaISA::IPR_IPLR: case IPR_IPLR:
case AlphaISA::IPR_INTID: case IPR_INTID:
case AlphaISA::IPR_PMCTR: case IPR_PMCTR:
// no side-effect // no side-effect
retval = ipr[idx]; retval = ipr[idx];
break; break;
case AlphaISA::IPR_CC: case IPR_CC:
retval |= ipr[idx] & ULL(0xffffffff00000000); retval |= ipr[idx] & ULL(0xffffffff00000000);
retval |= tc->getCpuPtr()->curCycle() & ULL(0x00000000ffffffff); retval |= tc->getCpuPtr()->curCycle() & ULL(0x00000000ffffffff);
break; break;
case AlphaISA::IPR_VA: case IPR_VA:
retval = ipr[idx]; retval = ipr[idx];
break; break;
case AlphaISA::IPR_VA_FORM: case IPR_VA_FORM:
case AlphaISA::IPR_MM_STAT: case IPR_MM_STAT:
case AlphaISA::IPR_IFAULT_VA_FORM: case IPR_IFAULT_VA_FORM:
case AlphaISA::IPR_EXC_MASK: case IPR_EXC_MASK:
case AlphaISA::IPR_EXC_SUM: case IPR_EXC_SUM:
retval = ipr[idx]; retval = ipr[idx];
break; break;
case AlphaISA::IPR_DTB_PTE: case IPR_DTB_PTE:
{ {
AlphaISA::TlbEntry &entry TlbEntry &entry
= tc->getDTBPtr()->index(!tc->misspeculating()); = tc->getDTBPtr()->index(!tc->misspeculating());
retval |= ((uint64_t)entry.ppn & ULL(0x7ffffff)) << 32; retval |= ((uint64_t)entry.ppn & ULL(0x7ffffff)) << 32;
@ -259,15 +243,15 @@ AlphaISA::MiscRegFile::readIpr(int idx, ThreadContext *tc)
break; break;
// write only registers // write only registers
case AlphaISA::IPR_HWINT_CLR: case IPR_HWINT_CLR:
case AlphaISA::IPR_SL_XMIT: case IPR_SL_XMIT:
case AlphaISA::IPR_DC_FLUSH: case IPR_DC_FLUSH:
case AlphaISA::IPR_IC_FLUSH: case IPR_IC_FLUSH:
case AlphaISA::IPR_ALT_MODE: case IPR_ALT_MODE:
case AlphaISA::IPR_DTB_IA: case IPR_DTB_IA:
case AlphaISA::IPR_DTB_IAP: case IPR_DTB_IAP:
case AlphaISA::IPR_ITB_IA: case IPR_ITB_IA:
case AlphaISA::IPR_ITB_IAP: case IPR_ITB_IAP:
panic("Tried to read write only register %d\n", idx); panic("Tried to read write only register %d\n", idx);
break; break;
@ -286,7 +270,7 @@ int break_ipl = -1;
#endif #endif
void void
AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc) MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc)
{ {
uint64_t old; uint64_t old;
@ -294,52 +278,52 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc)
return; return;
switch (idx) { switch (idx) {
case AlphaISA::IPR_PALtemp0: case IPR_PALtemp0:
case AlphaISA::IPR_PALtemp1: case IPR_PALtemp1:
case AlphaISA::IPR_PALtemp2: case IPR_PALtemp2:
case AlphaISA::IPR_PALtemp3: case IPR_PALtemp3:
case AlphaISA::IPR_PALtemp4: case IPR_PALtemp4:
case AlphaISA::IPR_PALtemp5: case IPR_PALtemp5:
case AlphaISA::IPR_PALtemp6: case IPR_PALtemp6:
case AlphaISA::IPR_PALtemp7: case IPR_PALtemp7:
case AlphaISA::IPR_PALtemp8: case IPR_PALtemp8:
case AlphaISA::IPR_PALtemp9: case IPR_PALtemp9:
case AlphaISA::IPR_PALtemp10: case IPR_PALtemp10:
case AlphaISA::IPR_PALtemp11: case IPR_PALtemp11:
case AlphaISA::IPR_PALtemp12: case IPR_PALtemp12:
case AlphaISA::IPR_PALtemp13: case IPR_PALtemp13:
case AlphaISA::IPR_PALtemp14: case IPR_PALtemp14:
case AlphaISA::IPR_PALtemp15: case IPR_PALtemp15:
case AlphaISA::IPR_PALtemp16: case IPR_PALtemp16:
case AlphaISA::IPR_PALtemp17: case IPR_PALtemp17:
case AlphaISA::IPR_PALtemp18: case IPR_PALtemp18:
case AlphaISA::IPR_PALtemp19: case IPR_PALtemp19:
case AlphaISA::IPR_PALtemp20: case IPR_PALtemp20:
case AlphaISA::IPR_PALtemp21: case IPR_PALtemp21:
case AlphaISA::IPR_PALtemp22: case IPR_PALtemp22:
case AlphaISA::IPR_PAL_BASE: case IPR_PAL_BASE:
case AlphaISA::IPR_IC_PERR_STAT: case IPR_IC_PERR_STAT:
case AlphaISA::IPR_DC_PERR_STAT: case IPR_DC_PERR_STAT:
case AlphaISA::IPR_PMCTR: case IPR_PMCTR:
// write entire quad w/ no side-effect // write entire quad w/ no side-effect
ipr[idx] = val; ipr[idx] = val;
break; break;
case AlphaISA::IPR_CC_CTL: case IPR_CC_CTL:
// This IPR resets the cycle counter. We assume this only // This IPR resets the cycle counter. We assume this only
// happens once... let's verify that. // happens once... let's verify that.
assert(ipr[idx] == 0); assert(ipr[idx] == 0);
ipr[idx] = 1; ipr[idx] = 1;
break; break;
case AlphaISA::IPR_CC: case IPR_CC:
// This IPR only writes the upper 64 bits. It's ok to write // This IPR only writes the upper 64 bits. It's ok to write
// all 64 here since we mask out the lower 32 in rpcc (see // all 64 here since we mask out the lower 32 in rpcc (see
// isa_desc). // isa_desc).
ipr[idx] = val; ipr[idx] = val;
break; break;
case AlphaISA::IPR_PALtemp23: case IPR_PALtemp23:
// write entire quad w/ no side-effect // write entire quad w/ no side-effect
old = ipr[idx]; old = ipr[idx];
ipr[idx] = val; ipr[idx] = val;
@ -349,23 +333,23 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc)
#endif #endif
break; break;
case AlphaISA::IPR_DTB_PTE: case IPR_DTB_PTE:
// write entire quad w/ no side-effect, tag is forthcoming // write entire quad w/ no side-effect, tag is forthcoming
ipr[idx] = val; ipr[idx] = val;
break; break;
case AlphaISA::IPR_EXC_ADDR: case IPR_EXC_ADDR:
// second least significant bit in PC is always zero // second least significant bit in PC is always zero
ipr[idx] = val & ~2; ipr[idx] = val & ~2;
break; break;
case AlphaISA::IPR_ASTRR: case IPR_ASTRR:
case AlphaISA::IPR_ASTER: case IPR_ASTER:
// only write least significant four bits - privilege mask // only write least significant four bits - privilege mask
ipr[idx] = val & 0xf; ipr[idx] = val & 0xf;
break; break;
case AlphaISA::IPR_IPLR: case IPR_IPLR:
#ifdef DEBUG #ifdef DEBUG
if (break_ipl != -1 && break_ipl == (val & 0x1f)) if (break_ipl != -1 && break_ipl == (val & 0x1f))
debug_break(); debug_break();
@ -379,175 +363,173 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc)
#endif #endif
break; break;
case AlphaISA::IPR_DTB_CM: case IPR_DTB_CM:
#if FULL_SYSTEM #if FULL_SYSTEM
if (val & 0x18) { if (val & 0x18) {
if (tc->getKernelStats()) if (tc->getKernelStats())
tc->getKernelStats()->mode(TheISA::Kernel::user, tc); tc->getKernelStats()->mode(Kernel::user, tc);
} else { } else {
if (tc->getKernelStats()) if (tc->getKernelStats())
tc->getKernelStats()->mode(TheISA::Kernel::kernel, tc); tc->getKernelStats()->mode(Kernel::kernel, tc);
} }
#endif #endif
case AlphaISA::IPR_ICM: case IPR_ICM:
// only write two mode bits - processor mode // only write two mode bits - processor mode
ipr[idx] = val & 0x18; ipr[idx] = val & 0x18;
break; break;
case AlphaISA::IPR_ALT_MODE: case IPR_ALT_MODE:
// only write two mode bits - processor mode // only write two mode bits - processor mode
ipr[idx] = val & 0x18; ipr[idx] = val & 0x18;
break; break;
case AlphaISA::IPR_MCSR: case IPR_MCSR:
// more here after optimization... // more here after optimization...
ipr[idx] = val; ipr[idx] = val;
break; break;
case AlphaISA::IPR_SIRR: case IPR_SIRR:
// only write software interrupt mask // only write software interrupt mask
ipr[idx] = val & 0x7fff0; ipr[idx] = val & 0x7fff0;
break; break;
case AlphaISA::IPR_ICSR: case IPR_ICSR:
ipr[idx] = val & ULL(0xffffff0300); ipr[idx] = val & ULL(0xffffff0300);
break; break;
case AlphaISA::IPR_IVPTBR: case IPR_IVPTBR:
case AlphaISA::IPR_MVPTBR: case IPR_MVPTBR:
ipr[idx] = val & ULL(0xffffffffc0000000); ipr[idx] = val & ULL(0xffffffffc0000000);
break; break;
case AlphaISA::IPR_DC_TEST_CTL: case IPR_DC_TEST_CTL:
ipr[idx] = val & 0x1ffb; ipr[idx] = val & 0x1ffb;
break; break;
case AlphaISA::IPR_DC_MODE: case IPR_DC_MODE:
case AlphaISA::IPR_MAF_MODE: case IPR_MAF_MODE:
ipr[idx] = val & 0x3f; ipr[idx] = val & 0x3f;
break; break;
case AlphaISA::IPR_ITB_ASN: case IPR_ITB_ASN:
ipr[idx] = val & 0x7f0; ipr[idx] = val & 0x7f0;
break; break;
case AlphaISA::IPR_DTB_ASN: case IPR_DTB_ASN:
ipr[idx] = val & ULL(0xfe00000000000000); ipr[idx] = val & ULL(0xfe00000000000000);
break; break;
case AlphaISA::IPR_EXC_SUM: case IPR_EXC_SUM:
case AlphaISA::IPR_EXC_MASK: case IPR_EXC_MASK:
// any write to this register clears it // any write to this register clears it
ipr[idx] = 0; ipr[idx] = 0;
break; break;
case AlphaISA::IPR_INTID: case IPR_INTID:
case AlphaISA::IPR_SL_RCV: case IPR_SL_RCV:
case AlphaISA::IPR_MM_STAT: case IPR_MM_STAT:
case AlphaISA::IPR_ITB_PTE_TEMP: case IPR_ITB_PTE_TEMP:
case AlphaISA::IPR_DTB_PTE_TEMP: case IPR_DTB_PTE_TEMP:
// read-only registers // read-only registers
panic("Tried to write read only ipr %d\n", idx); panic("Tried to write read only ipr %d\n", idx);
case AlphaISA::IPR_HWINT_CLR: case IPR_HWINT_CLR:
case AlphaISA::IPR_SL_XMIT: case IPR_SL_XMIT:
case AlphaISA::IPR_DC_FLUSH: case IPR_DC_FLUSH:
case AlphaISA::IPR_IC_FLUSH: case IPR_IC_FLUSH:
// the following are write only // the following are write only
ipr[idx] = val; ipr[idx] = val;
break; break;
case AlphaISA::IPR_DTB_IA: case IPR_DTB_IA:
// really a control write // really a control write
ipr[idx] = 0; ipr[idx] = 0;
tc->getDTBPtr()->flushAll(); tc->getDTBPtr()->flushAll();
break; break;
case AlphaISA::IPR_DTB_IAP: case IPR_DTB_IAP:
// really a control write // really a control write
ipr[idx] = 0; ipr[idx] = 0;
tc->getDTBPtr()->flushProcesses(); tc->getDTBPtr()->flushProcesses();
break; break;
case AlphaISA::IPR_DTB_IS: case IPR_DTB_IS:
// really a control write // really a control write
ipr[idx] = val; ipr[idx] = val;
tc->getDTBPtr()->flushAddr(val, tc->getDTBPtr()->flushAddr(val, DTB_ASN_ASN(ipr[IPR_DTB_ASN]));
EV5::DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
break; break;
case AlphaISA::IPR_DTB_TAG: { case IPR_DTB_TAG: {
struct AlphaISA::TlbEntry entry; struct TlbEntry entry;
// FIXME: granularity hints NYI... // FIXME: granularity hints NYI...
if (EV5::DTB_PTE_GH(ipr[AlphaISA::IPR_DTB_PTE]) != 0) if (DTB_PTE_GH(ipr[IPR_DTB_PTE]) != 0)
panic("PTE GH field != 0"); panic("PTE GH field != 0");
// write entire quad // write entire quad
ipr[idx] = val; ipr[idx] = val;
// construct PTE for new entry // construct PTE for new entry
entry.ppn = EV5::DTB_PTE_PPN(ipr[AlphaISA::IPR_DTB_PTE]); entry.ppn = DTB_PTE_PPN(ipr[IPR_DTB_PTE]);
entry.xre = EV5::DTB_PTE_XRE(ipr[AlphaISA::IPR_DTB_PTE]); entry.xre = DTB_PTE_XRE(ipr[IPR_DTB_PTE]);
entry.xwe = EV5::DTB_PTE_XWE(ipr[AlphaISA::IPR_DTB_PTE]); entry.xwe = DTB_PTE_XWE(ipr[IPR_DTB_PTE]);
entry.fonr = EV5::DTB_PTE_FONR(ipr[AlphaISA::IPR_DTB_PTE]); entry.fonr = DTB_PTE_FONR(ipr[IPR_DTB_PTE]);
entry.fonw = EV5::DTB_PTE_FONW(ipr[AlphaISA::IPR_DTB_PTE]); entry.fonw = DTB_PTE_FONW(ipr[IPR_DTB_PTE]);
entry.asma = EV5::DTB_PTE_ASMA(ipr[AlphaISA::IPR_DTB_PTE]); entry.asma = DTB_PTE_ASMA(ipr[IPR_DTB_PTE]);
entry.asn = EV5::DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]); entry.asn = DTB_ASN_ASN(ipr[IPR_DTB_ASN]);
// insert new TAG/PTE value into data TLB // insert new TAG/PTE value into data TLB
tc->getDTBPtr()->insert(val, entry); tc->getDTBPtr()->insert(val, entry);
} }
break; break;
case AlphaISA::IPR_ITB_PTE: { case IPR_ITB_PTE: {
struct AlphaISA::TlbEntry entry; struct TlbEntry entry;
// FIXME: granularity hints NYI... // FIXME: granularity hints NYI...
if (EV5::ITB_PTE_GH(val) != 0) if (ITB_PTE_GH(val) != 0)
panic("PTE GH field != 0"); panic("PTE GH field != 0");
// write entire quad // write entire quad
ipr[idx] = val; ipr[idx] = val;
// construct PTE for new entry // construct PTE for new entry
entry.ppn = EV5::ITB_PTE_PPN(val); entry.ppn = ITB_PTE_PPN(val);
entry.xre = EV5::ITB_PTE_XRE(val); entry.xre = ITB_PTE_XRE(val);
entry.xwe = 0; entry.xwe = 0;
entry.fonr = EV5::ITB_PTE_FONR(val); entry.fonr = ITB_PTE_FONR(val);
entry.fonw = EV5::ITB_PTE_FONW(val); entry.fonw = ITB_PTE_FONW(val);
entry.asma = EV5::ITB_PTE_ASMA(val); entry.asma = ITB_PTE_ASMA(val);
entry.asn = EV5::ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]); entry.asn = ITB_ASN_ASN(ipr[IPR_ITB_ASN]);
// insert new TAG/PTE value into data TLB // insert new TAG/PTE value into data TLB
tc->getITBPtr()->insert(ipr[AlphaISA::IPR_ITB_TAG], entry); tc->getITBPtr()->insert(ipr[IPR_ITB_TAG], entry);
} }
break; break;
case AlphaISA::IPR_ITB_IA: case IPR_ITB_IA:
// really a control write // really a control write
ipr[idx] = 0; ipr[idx] = 0;
tc->getITBPtr()->flushAll(); tc->getITBPtr()->flushAll();
break; break;
case AlphaISA::IPR_ITB_IAP: case IPR_ITB_IAP:
// really a control write // really a control write
ipr[idx] = 0; ipr[idx] = 0;
tc->getITBPtr()->flushProcesses(); tc->getITBPtr()->flushProcesses();
break; break;
case AlphaISA::IPR_ITB_IS: case IPR_ITB_IS:
// really a control write // really a control write
ipr[idx] = val; ipr[idx] = val;
tc->getITBPtr()->flushAddr(val, tc->getITBPtr()->flushAddr(val, ITB_ASN_ASN(ipr[IPR_ITB_ASN]));
EV5::ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]));
break; break;
default: default:
@ -558,17 +540,38 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc)
// no error... // no error...
} }
void void
AlphaISA::copyIprs(ThreadContext *src, ThreadContext *dest) copyIprs(ThreadContext *src, ThreadContext *dest)
{ {
for (int i = 0; i < NumInternalProcRegs; ++i) { for (int i = 0; i < NumInternalProcRegs; ++i)
dest->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i)); dest->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i));
}
} }
} // namespace AlphaISA
#if FULL_SYSTEM #if FULL_SYSTEM
using namespace AlphaISA;
Fault
SimpleThread::hwrei()
{
if (!(readPC() & 0x3))
return new UnimplementedOpcodeFault;
setNextPC(readMiscRegNoEffect(IPR_EXC_ADDR));
CPA::cpa()->swAutoBegin(tc, readNextPC());
if (!misspeculating()) {
if (kernelStats)
kernelStats->hwrei();
}
// FIXME: XXX check for interrupts? XXX
return NoFault;
}
/** /**
* Check for special simulator handling of specific PAL calls. * Check for special simulator handling of specific PAL calls.
* If return value is false, actual PAL call will be suppressed. * If return value is false, actual PAL call will be suppressed.

View file

@ -36,10 +36,7 @@
#include "config/alpha_tlaser.hh" #include "config/alpha_tlaser.hh"
#include "arch/alpha/isa_traits.hh" #include "arch/alpha/isa_traits.hh"
namespace EV5 { namespace AlphaISA {
//It seems like a safe assumption EV5 only applies to alpha
using namespace AlphaISA;
#if ALPHA_TLASER #if ALPHA_TLASER
const uint64_t AsnMask = ULL(0x7f); const uint64_t AsnMask = ULL(0x7f);
@ -51,8 +48,8 @@ const int VAddrImplBits = 43;
const Addr VAddrImplMask = (ULL(1) << VAddrImplBits) - 1; const Addr VAddrImplMask = (ULL(1) << VAddrImplBits) - 1;
const Addr VAddrUnImplMask = ~VAddrImplMask; const Addr VAddrUnImplMask = ~VAddrImplMask;
inline Addr VAddrImpl(Addr a) { return a & VAddrImplMask; } inline Addr VAddrImpl(Addr a) { return a & VAddrImplMask; }
inline Addr VAddrVPN(Addr a) { return a >> AlphaISA::PageShift; } inline Addr VAddrVPN(Addr a) { return a >> PageShift; }
inline Addr VAddrOffset(Addr a) { return a & AlphaISA::PageOffset; } inline Addr VAddrOffset(Addr a) { return a & PageOffset; }
inline Addr VAddrSpaceEV5(Addr a) { return a >> 41 & 0x3; } inline Addr VAddrSpaceEV5(Addr a) { return a >> 41 & 0x3; }
inline Addr VAddrSpaceEV6(Addr a) { return a >> 41 & 0x7f; } inline Addr VAddrSpaceEV6(Addr a) { return a >> 41 & 0x7f; }
@ -68,7 +65,9 @@ const Addr PAddrUncachedBit39 = ULL(0x8000000000);
const Addr PAddrUncachedBit40 = ULL(0x10000000000); const Addr PAddrUncachedBit40 = ULL(0x10000000000);
const Addr PAddrUncachedBit43 = ULL(0x80000000000); const Addr PAddrUncachedBit43 = ULL(0x80000000000);
const Addr PAddrUncachedMask = ULL(0x807ffffffff); // Clear PA<42:35> const Addr PAddrUncachedMask = ULL(0x807ffffffff); // Clear PA<42:35>
inline Addr Phys2K0Seg(Addr addr)
inline Addr
Phys2K0Seg(Addr addr)
{ {
#if !ALPHA_TLASER #if !ALPHA_TLASER
if (addr & PAddrUncachedBit43) { if (addr & PAddrUncachedBit43) {
@ -76,12 +75,12 @@ inline Addr Phys2K0Seg(Addr addr)
addr |= PAddrUncachedBit40; addr |= PAddrUncachedBit40;
} }
#endif #endif
return addr | AlphaISA::K0SegBase; return addr | K0SegBase;
} }
inline int DTB_ASN_ASN(uint64_t reg) { return reg >> 57 & AsnMask; } inline int DTB_ASN_ASN(uint64_t reg) { return reg >> 57 & AsnMask; }
inline Addr DTB_PTE_PPN(uint64_t reg) inline Addr DTB_PTE_PPN(uint64_t reg)
{ return reg >> 32 & (ULL(1) << PAddrImplBits - AlphaISA::PageShift) - 1; } { return reg >> 32 & ((ULL(1) << (PAddrImplBits - PageShift)) - 1); }
inline int DTB_PTE_XRE(uint64_t reg) { return reg >> 8 & 0xf; } inline int DTB_PTE_XRE(uint64_t reg) { return reg >> 8 & 0xf; }
inline int DTB_PTE_XWE(uint64_t reg) { return reg >> 12 & 0xf; } inline int DTB_PTE_XWE(uint64_t reg) { return reg >> 12 & 0xf; }
inline int DTB_PTE_FONR(uint64_t reg) { return reg >> 1 & 0x1; } inline int DTB_PTE_FONR(uint64_t reg) { return reg >> 1 & 0x1; }
@ -91,7 +90,7 @@ inline int DTB_PTE_ASMA(uint64_t reg) { return reg >> 4 & 0x1; }
inline int ITB_ASN_ASN(uint64_t reg) { return reg >> 4 & AsnMask; } inline int ITB_ASN_ASN(uint64_t reg) { return reg >> 4 & AsnMask; }
inline Addr ITB_PTE_PPN(uint64_t reg) inline Addr ITB_PTE_PPN(uint64_t reg)
{ return reg >> 32 & (ULL(1) << PAddrImplBits - AlphaISA::PageShift) - 1; } { return reg >> 32 & ((ULL(1) << (PAddrImplBits - PageShift)) - 1); }
inline int ITB_PTE_XRE(uint64_t reg) { return reg >> 8 & 0xf; } inline int ITB_PTE_XRE(uint64_t reg) { return reg >> 8 & 0xf; }
inline bool ITB_PTE_FONR(uint64_t reg) { return reg >> 1 & 0x1; } inline bool ITB_PTE_FONR(uint64_t reg) { return reg >> 1 & 0x1; }
inline bool ITB_PTE_FONW(uint64_t reg) { return reg >> 2 & 0x1; } inline bool ITB_PTE_FONW(uint64_t reg) { return reg >> 2 & 0x1; }
@ -114,12 +113,12 @@ const uint64_t MM_STAT_FONW_MASK = ULL(0x0008);
const uint64_t MM_STAT_FONR_MASK = ULL(0x0004); const uint64_t MM_STAT_FONR_MASK = ULL(0x0004);
const uint64_t MM_STAT_ACV_MASK = ULL(0x0002); const uint64_t MM_STAT_ACV_MASK = ULL(0x0002);
const uint64_t MM_STAT_WR_MASK = ULL(0x0001); const uint64_t MM_STAT_WR_MASK = ULL(0x0001);
inline int Opcode(AlphaISA::MachInst inst) { return inst >> 26 & 0x3f; } inline int Opcode(MachInst inst) { return inst >> 26 & 0x3f; }
inline int Ra(AlphaISA::MachInst inst) { return inst >> 21 & 0x1f; } inline int Ra(MachInst inst) { return inst >> 21 & 0x1f; }
const Addr PalBase = 0x4000; const Addr PalBase = 0x4000;
const Addr PalMax = 0x10000; const Addr PalMax = 0x10000;
/* namespace EV5 */ } } // namespace AlphaISA
#endif // __ARCH_ALPHA_EV5_HH__ #endif // __ARCH_ALPHA_EV5_HH__

View file

@ -40,8 +40,7 @@
#include "mem/page_table.hh" #include "mem/page_table.hh"
#endif #endif
namespace AlphaISA namespace AlphaISA {
{
FaultName MachineCheckFault::_name = "mchk"; FaultName MachineCheckFault::_name = "mchk";
FaultVect MachineCheckFault::_vect = 0x0401; FaultVect MachineCheckFault::_vect = 0x0401;
@ -109,64 +108,67 @@ FaultStat IntegerOverflowFault::_count;
#if FULL_SYSTEM #if FULL_SYSTEM
void AlphaFault::invoke(ThreadContext * tc) void
AlphaFault::invoke(ThreadContext *tc)
{ {
FaultBase::invoke(tc); FaultBase::invoke(tc);
countStat()++; countStat()++;
// exception restart address // exception restart address
if (setRestartAddress() || !(tc->readPC() & 0x3)) if (setRestartAddress() || !(tc->readPC() & 0x3))
tc->setMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR, tc->readPC()); tc->setMiscRegNoEffect(IPR_EXC_ADDR, tc->readPC());
if (skipFaultingInstruction()) { if (skipFaultingInstruction()) {
// traps... skip faulting instruction. // traps... skip faulting instruction.
tc->setMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR, tc->setMiscRegNoEffect(IPR_EXC_ADDR,
tc->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR) + 4); tc->readMiscRegNoEffect(IPR_EXC_ADDR) + 4);
} }
tc->setPC(tc->readMiscRegNoEffect(AlphaISA::IPR_PAL_BASE) + vect()); tc->setPC(tc->readMiscRegNoEffect(IPR_PAL_BASE) + vect());
tc->setNextPC(tc->readPC() + sizeof(MachInst)); tc->setNextPC(tc->readPC() + sizeof(MachInst));
} }
void ArithmeticFault::invoke(ThreadContext * tc) void
ArithmeticFault::invoke(ThreadContext *tc)
{ {
FaultBase::invoke(tc); FaultBase::invoke(tc);
panic("Arithmetic traps are unimplemented!"); panic("Arithmetic traps are unimplemented!");
} }
void DtbFault::invoke(ThreadContext * tc) void
DtbFault::invoke(ThreadContext *tc)
{ {
// Set fault address and flags. Even though we're modeling an // Set fault address and flags. Even though we're modeling an
// EV5, we use the EV6 technique of not latching fault registers // EV5, we use the EV6 technique of not latching fault registers
// on VPTE loads (instead of locking the registers until IPR_VA is // on VPTE loads (instead of locking the registers until IPR_VA is
// read, like the EV5). The EV6 approach is cleaner and seems to // read, like the EV5). The EV6 approach is cleaner and seems to
// work with EV5 PAL code, but not the other way around. // work with EV5 PAL code, but not the other way around.
if (!tc->misspeculating() if (!tc->misspeculating() &&
&& !(reqFlags & VPTE) && !(reqFlags & NO_FAULT)) { reqFlags.noneSet(Request::VPTE|Request::NO_FAULT)) {
// set VA register with faulting address // set VA register with faulting address
tc->setMiscRegNoEffect(AlphaISA::IPR_VA, vaddr); tc->setMiscRegNoEffect(IPR_VA, vaddr);
// set MM_STAT register flags // set MM_STAT register flags
tc->setMiscRegNoEffect(AlphaISA::IPR_MM_STAT, tc->setMiscRegNoEffect(IPR_MM_STAT,
(((EV5::Opcode(tc->getInst()) & 0x3f) << 11) (((Opcode(tc->getInst()) & 0x3f) << 11) |
| ((EV5::Ra(tc->getInst()) & 0x1f) << 6) ((Ra(tc->getInst()) & 0x1f) << 6) |
| (flags & 0x3f))); (flags & 0x3f)));
// set VA_FORM register with faulting formatted address // set VA_FORM register with faulting formatted address
tc->setMiscRegNoEffect(AlphaISA::IPR_VA_FORM, tc->setMiscRegNoEffect(IPR_VA_FORM,
tc->readMiscRegNoEffect(AlphaISA::IPR_MVPTBR) | (vaddr.vpn() << 3)); tc->readMiscRegNoEffect(IPR_MVPTBR) | (vaddr.vpn() << 3));
} }
AlphaFault::invoke(tc); AlphaFault::invoke(tc);
} }
void ItbFault::invoke(ThreadContext * tc) void
ItbFault::invoke(ThreadContext *tc)
{ {
if (!tc->misspeculating()) { if (!tc->misspeculating()) {
tc->setMiscRegNoEffect(AlphaISA::IPR_ITB_TAG, pc); tc->setMiscRegNoEffect(IPR_ITB_TAG, pc);
tc->setMiscRegNoEffect(AlphaISA::IPR_IFAULT_VA_FORM, tc->setMiscRegNoEffect(IPR_IFAULT_VA_FORM,
tc->readMiscRegNoEffect(AlphaISA::IPR_IVPTBR) | tc->readMiscRegNoEffect(IPR_IVPTBR) | (VAddr(pc).vpn() << 3));
(AlphaISA::VAddr(pc).vpn() << 3));
} }
AlphaFault::invoke(tc); AlphaFault::invoke(tc);
@ -174,12 +176,13 @@ void ItbFault::invoke(ThreadContext * tc)
#else #else
void ItbPageFault::invoke(ThreadContext * tc) void
ItbPageFault::invoke(ThreadContext *tc)
{ {
Process *p = tc->getProcessPtr(); Process *p = tc->getProcessPtr();
TlbEntry entry; TlbEntry entry;
bool success = p->pTable->lookup(pc, entry); bool success = p->pTable->lookup(pc, entry);
if(!success) { if (!success) {
panic("Tried to execute unmapped address %#x.\n", pc); panic("Tried to execute unmapped address %#x.\n", pc);
} else { } else {
VAddr vaddr(pc); VAddr vaddr(pc);
@ -187,16 +190,17 @@ void ItbPageFault::invoke(ThreadContext * tc)
} }
} }
void NDtbMissFault::invoke(ThreadContext * tc) void
NDtbMissFault::invoke(ThreadContext *tc)
{ {
Process *p = tc->getProcessPtr(); Process *p = tc->getProcessPtr();
TlbEntry entry; TlbEntry entry;
bool success = p->pTable->lookup(vaddr, entry); bool success = p->pTable->lookup(vaddr, entry);
if(!success) { if (!success) {
p->checkAndAllocNextPage(vaddr); p->checkAndAllocNextPage(vaddr);
success = p->pTable->lookup(vaddr, entry); success = p->pTable->lookup(vaddr, entry);
} }
if(!success) { if (!success) {
panic("Tried to access unmapped address %#x.\n", (Addr)vaddr); panic("Tried to access unmapped address %#x.\n", (Addr)vaddr);
} else { } else {
tc->getDTBPtr()->insert(vaddr.page(), entry); tc->getDTBPtr()->insert(vaddr.page(), entry);

View file

@ -29,18 +29,16 @@
* Kevin Lim * Kevin Lim
*/ */
#ifndef __ALPHA_FAULTS_HH__ #ifndef __ARCH_ALPHA_FAULTS_HH__
#define __ALPHA_FAULTS_HH__ #define __ARCH_ALPHA_FAULTS_HH__
#include "arch/alpha/pagetable.hh"
#include "config/full_system.hh" #include "config/full_system.hh"
#include "sim/faults.hh" #include "sim/faults.hh"
#include "arch/alpha/pagetable.hh"
// The design of the "name" and "vect" functions is in sim/faults.hh // The design of the "name" and "vect" functions is in sim/faults.hh
namespace AlphaISA namespace AlphaISA {
{
typedef const Addr FaultVect; typedef const Addr FaultVect;
@ -63,6 +61,7 @@ class MachineCheckFault : public AlphaFault
static FaultName _name; static FaultName _name;
static FaultVect _vect; static FaultVect _vect;
static FaultStat _count; static FaultStat _count;
public: public:
FaultName name() const {return _name;} FaultName name() const {return _name;}
FaultVect vect() {return _vect;} FaultVect vect() {return _vect;}
@ -76,6 +75,7 @@ class AlignmentFault : public AlphaFault
static FaultName _name; static FaultName _name;
static FaultVect _vect; static FaultVect _vect;
static FaultStat _count; static FaultStat _count;
public: public:
FaultName name() const {return _name;} FaultName name() const {return _name;}
FaultVect vect() {return _vect;} FaultVect vect() {return _vect;}
@ -94,6 +94,7 @@ class ResetFault : public AlphaFault
static FaultName _name; static FaultName _name;
static FaultVect _vect; static FaultVect _vect;
static FaultStat _count; static FaultStat _count;
public: public:
FaultName name() const {return _name;} FaultName name() const {return _name;}
FaultVect vect() {return _vect;} FaultVect vect() {return _vect;}
@ -102,12 +103,14 @@ class ResetFault : public AlphaFault
class ArithmeticFault : public AlphaFault class ArithmeticFault : public AlphaFault
{ {
protected:
bool skipFaultingInstruction() {return true;}
private: private:
static FaultName _name; static FaultName _name;
static FaultVect _vect; static FaultVect _vect;
static FaultStat _count; static FaultStat _count;
protected:
bool skipFaultingInstruction() {return true;}
public: public:
FaultName name() const {return _name;} FaultName name() const {return _name;}
FaultVect vect() {return _vect;} FaultVect vect() {return _vect;}
@ -119,12 +122,14 @@ class ArithmeticFault : public AlphaFault
class InterruptFault : public AlphaFault class InterruptFault : public AlphaFault
{ {
protected:
bool setRestartAddress() {return false;}
private: private:
static FaultName _name; static FaultName _name;
static FaultVect _vect; static FaultVect _vect;
static FaultStat _count; static FaultStat _count;
protected:
bool setRestartAddress() {return false;}
public: public:
FaultName name() const {return _name;} FaultName name() const {return _name;}
FaultVect vect() {return _vect;} FaultVect vect() {return _vect;}
@ -134,11 +139,12 @@ class InterruptFault : public AlphaFault
class DtbFault : public AlphaFault class DtbFault : public AlphaFault
{ {
protected: protected:
AlphaISA::VAddr vaddr; VAddr vaddr;
uint32_t reqFlags; Request::Flags reqFlags;
uint64_t flags; uint64_t flags;
public: public:
DtbFault(AlphaISA::VAddr _vaddr, uint32_t _reqFlags, uint64_t _flags) DtbFault(VAddr _vaddr, Request::Flags _reqFlags, uint64_t _flags)
: vaddr(_vaddr), reqFlags(_reqFlags), flags(_flags) : vaddr(_vaddr), reqFlags(_reqFlags), flags(_flags)
{ } { }
FaultName name() const = 0; FaultName name() const = 0;
@ -155,8 +161,9 @@ class NDtbMissFault : public DtbFault
static FaultName _name; static FaultName _name;
static FaultVect _vect; static FaultVect _vect;
static FaultStat _count; static FaultStat _count;
public: public:
NDtbMissFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags) NDtbMissFault(VAddr vaddr, Request::Flags reqFlags, uint64_t flags)
: DtbFault(vaddr, reqFlags, flags) : DtbFault(vaddr, reqFlags, flags)
{ } { }
FaultName name() const {return _name;} FaultName name() const {return _name;}
@ -173,8 +180,9 @@ class PDtbMissFault : public DtbFault
static FaultName _name; static FaultName _name;
static FaultVect _vect; static FaultVect _vect;
static FaultStat _count; static FaultStat _count;
public: public:
PDtbMissFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags) PDtbMissFault(VAddr vaddr, Request::Flags reqFlags, uint64_t flags)
: DtbFault(vaddr, reqFlags, flags) : DtbFault(vaddr, reqFlags, flags)
{ } { }
FaultName name() const {return _name;} FaultName name() const {return _name;}
@ -188,8 +196,9 @@ class DtbPageFault : public DtbFault
static FaultName _name; static FaultName _name;
static FaultVect _vect; static FaultVect _vect;
static FaultStat _count; static FaultStat _count;
public: public:
DtbPageFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags) DtbPageFault(VAddr vaddr, Request::Flags reqFlags, uint64_t flags)
: DtbFault(vaddr, reqFlags, flags) : DtbFault(vaddr, reqFlags, flags)
{ } { }
FaultName name() const {return _name;} FaultName name() const {return _name;}
@ -203,8 +212,9 @@ class DtbAcvFault : public DtbFault
static FaultName _name; static FaultName _name;
static FaultVect _vect; static FaultVect _vect;
static FaultStat _count; static FaultStat _count;
public: public:
DtbAcvFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags) DtbAcvFault(VAddr vaddr, Request::Flags reqFlags, uint64_t flags)
: DtbFault(vaddr, reqFlags, flags) : DtbFault(vaddr, reqFlags, flags)
{ } { }
FaultName name() const {return _name;} FaultName name() const {return _name;}
@ -218,8 +228,9 @@ class DtbAlignmentFault : public DtbFault
static FaultName _name; static FaultName _name;
static FaultVect _vect; static FaultVect _vect;
static FaultStat _count; static FaultStat _count;
public: public:
DtbAlignmentFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags) DtbAlignmentFault(VAddr vaddr, Request::Flags reqFlags, uint64_t flags)
: DtbFault(vaddr, reqFlags, flags) : DtbFault(vaddr, reqFlags, flags)
{ } { }
FaultName name() const {return _name;} FaultName name() const {return _name;}
@ -231,10 +242,9 @@ class ItbFault : public AlphaFault
{ {
protected: protected:
Addr pc; Addr pc;
public: public:
ItbFault(Addr _pc) ItbFault(Addr _pc) : pc(_pc) { }
: pc(_pc)
{ }
FaultName name() const = 0; FaultName name() const = 0;
FaultVect vect() = 0; FaultVect vect() = 0;
FaultStat & countStat() = 0; FaultStat & countStat() = 0;
@ -249,10 +259,9 @@ class ItbPageFault : public ItbFault
static FaultName _name; static FaultName _name;
static FaultVect _vect; static FaultVect _vect;
static FaultStat _count; static FaultStat _count;
public: public:
ItbPageFault(Addr pc) ItbPageFault(Addr pc) : ItbFault(pc) { }
: ItbFault(pc)
{ }
FaultName name() const {return _name;} FaultName name() const {return _name;}
FaultVect vect() {return _vect;} FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;} FaultStat & countStat() {return _count;}
@ -267,10 +276,9 @@ class ItbAcvFault : public ItbFault
static FaultName _name; static FaultName _name;
static FaultVect _vect; static FaultVect _vect;
static FaultStat _count; static FaultStat _count;
public: public:
ItbAcvFault(Addr pc) ItbAcvFault(Addr pc) : ItbFault(pc) { }
: ItbFault(pc)
{ }
FaultName name() const {return _name;} FaultName name() const {return _name;}
FaultVect vect() {return _vect;} FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;} FaultStat & countStat() {return _count;}
@ -282,6 +290,7 @@ class UnimplementedOpcodeFault : public AlphaFault
static FaultName _name; static FaultName _name;
static FaultVect _vect; static FaultVect _vect;
static FaultStat _count; static FaultStat _count;
public: public:
FaultName name() const {return _name;} FaultName name() const {return _name;}
FaultVect vect() {return _vect;} FaultVect vect() {return _vect;}
@ -294,6 +303,7 @@ class FloatEnableFault : public AlphaFault
static FaultName _name; static FaultName _name;
static FaultVect _vect; static FaultVect _vect;
static FaultStat _count; static FaultStat _count;
public: public:
FaultName name() const {return _name;} FaultName name() const {return _name;}
FaultVect vect() {return _vect;} FaultVect vect() {return _vect;}
@ -302,12 +312,14 @@ class FloatEnableFault : public AlphaFault
class PalFault : public AlphaFault class PalFault : public AlphaFault
{ {
protected:
bool skipFaultingInstruction() {return true;}
private: private:
static FaultName _name; static FaultName _name;
static FaultVect _vect; static FaultVect _vect;
static FaultStat _count; static FaultStat _count;
protected:
bool skipFaultingInstruction() {return true;}
public: public:
FaultName name() const {return _name;} FaultName name() const {return _name;}
FaultVect vect() {return _vect;} FaultVect vect() {return _vect;}
@ -320,12 +332,13 @@ class IntegerOverflowFault : public AlphaFault
static FaultName _name; static FaultName _name;
static FaultVect _vect; static FaultVect _vect;
static FaultStat _count; static FaultStat _count;
public: public:
FaultName name() const {return _name;} FaultName name() const {return _name;}
FaultVect vect() {return _vect;} FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;} FaultStat & countStat() {return _count;}
}; };
} // AlphaISA namespace } // namespace AlphaISA
#endif // __FAULTS_HH__ #endif // __ARCH_ALPHA_FAULTS_HH__

View file

@ -30,20 +30,28 @@
* Kevin Lim * Kevin Lim
*/ */
#include <cstring>
#include "arch/alpha/floatregfile.hh" #include "arch/alpha/floatregfile.hh"
#include "sim/serialize.hh" #include "sim/serialize.hh"
namespace AlphaISA namespace AlphaISA {
void
FloatRegFile::clear()
{ {
void std::memset(d, 0, sizeof(d));
FloatRegFile::serialize(std::ostream &os)
{
SERIALIZE_ARRAY(q, NumFloatRegs);
}
void
FloatRegFile::unserialize(Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_ARRAY(q, NumFloatRegs);
}
} }
void
FloatRegFile::serialize(std::ostream &os)
{
SERIALIZE_ARRAY(q, NumFloatRegs);
}
void
FloatRegFile::unserialize(Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_ARRAY(q, NumFloatRegs);
}
} // namespace AlphaISA

View file

@ -32,37 +32,30 @@
#ifndef __ARCH_ALPHA_FLOATREGFILE_HH__ #ifndef __ARCH_ALPHA_FLOATREGFILE_HH__
#define __ARCH_ALPHA_FLOATREGFILE_HH__ #define __ARCH_ALPHA_FLOATREGFILE_HH__
#include <iosfwd>
#include <string>
#include "arch/alpha/isa_traits.hh" #include "arch/alpha/isa_traits.hh"
#include "arch/alpha/types.hh" #include "arch/alpha/types.hh"
#include <cstring>
#include <iostream>
class Checkpoint; class Checkpoint;
namespace AlphaISA namespace AlphaISA {
class FloatRegFile
{ {
static inline std::string getFloatRegName(RegIndex) public:
{ union {
return ""; uint64_t q[NumFloatRegs]; // integer qword view
} double d[NumFloatRegs]; // double-precision floating point view
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()
{ std::memset(d, 0, sizeof(d)); }
}; };
}
#endif void clear();
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
};
} // namespace AlphaISA
#endif // __ARCH_ALPHA_FLOATREGFILE_HH__

View file

@ -62,29 +62,25 @@ FreebsdAlphaSystem::FreebsdAlphaSystem(Params *p)
addKernelFuncEvent<SkipCalibrateClocksEvent>("calibrate_clocks"); addKernelFuncEvent<SkipCalibrateClocksEvent>("calibrate_clocks");
} }
FreebsdAlphaSystem::~FreebsdAlphaSystem() FreebsdAlphaSystem::~FreebsdAlphaSystem()
{ {
delete skipDelayEvent; delete skipDelayEvent;
delete skipCalibrateClocks; delete skipCalibrateClocks;
} }
void void
FreebsdAlphaSystem::doCalibrateClocks(ThreadContext *tc) FreebsdAlphaSystem::doCalibrateClocks(ThreadContext *tc)
{ {
Addr ppc_vaddr = 0; Addr ppc_vaddr = 0;
Addr timer_vaddr = 0; Addr timer_vaddr = 0;
assert(NumArgumentRegs >= 3); ppc_vaddr = (Addr)tc->readIntReg(17);
ppc_vaddr = (Addr)tc->readIntReg(ArgumentReg[1]); timer_vaddr = (Addr)tc->readIntReg(18);
timer_vaddr = (Addr)tc->readIntReg(ArgumentReg[2]);
virtPort.write(ppc_vaddr, (uint32_t)Clock::Frequency); virtPort.write(ppc_vaddr, (uint32_t)Clock::Frequency);
virtPort.write(timer_vaddr, (uint32_t)TIMER_FREQUENCY); virtPort.write(timer_vaddr, (uint32_t)TIMER_FREQUENCY);
} }
void void
FreebsdAlphaSystem::SkipCalibrateClocksEvent::process(ThreadContext *tc) FreebsdAlphaSystem::SkipCalibrateClocksEvent::process(ThreadContext *tc)
{ {

View file

@ -57,7 +57,6 @@ class FreebsdAlphaSystem : public AlphaSystem
~FreebsdAlphaSystem(); ~FreebsdAlphaSystem();
void doCalibrateClocks(ThreadContext *tc); void doCalibrateClocks(ThreadContext *tc);
}; };
#endif // __ARCH_ALPHA_FREEBSD_SYSTEM_HH__ #endif // __ARCH_ALPHA_FREEBSD_SYSTEM_HH__

View file

@ -33,13 +33,14 @@
#include "arch/alpha/kernel_stats.hh" #include "arch/alpha/kernel_stats.hh"
#include "cpu/thread_context.hh" #include "cpu/thread_context.hh"
using namespace TheISA; using namespace AlphaISA;
void void
IdleStartEvent::process(ThreadContext *tc) IdleStartEvent::process(ThreadContext *tc)
{ {
if (tc->getKernelStats()) if (tc->getKernelStats()) {
tc->getKernelStats()->setIdleProcess( MiscReg val = tc->readMiscRegNoEffect(IPR_PALtemp23);
tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp23), tc); tc->getKernelStats()->setIdleProcess(val, tc);
}
remove(); remove();
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004-2006 The Regents of The University of Michigan * Copyright (c) 2008 The Regents of The University of Michigan
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -28,8 +28,10 @@
* Authors: Gabe Black * Authors: Gabe Black
*/ */
#include "cpu/o3/thread_context.hh" #include "arch/alpha/interrupts.hh"
#include "cpu/o3/thread_context_impl.hh"
template class O3ThreadContext<SparcSimpleImpl>;
AlphaISA::Interrupts *
AlphaInterruptsParams::create()
{
return new AlphaISA::Interrupts(this);
}

View file

@ -35,142 +35,163 @@
#include "arch/alpha/faults.hh" #include "arch/alpha/faults.hh"
#include "arch/alpha/isa_traits.hh" #include "arch/alpha/isa_traits.hh"
#include "base/compiler.hh" #include "base/compiler.hh"
#include "base/trace.hh"
#include "cpu/thread_context.hh" #include "cpu/thread_context.hh"
#include "params/AlphaInterrupts.hh"
#include "sim/sim_object.hh"
namespace AlphaISA namespace AlphaISA {
class Interrupts : public SimObject
{ {
class Interrupts private:
bool newInfoSet;
int newIpl;
int newSummary;
BaseCPU * cpu;
protected:
uint64_t interrupts[NumInterruptLevels];
uint64_t intstatus;
public:
typedef AlphaInterruptsParams Params;
const Params *
params() const
{ {
protected: return dynamic_cast<const Params *>(_params);
uint64_t interrupts[NumInterruptLevels]; }
uint64_t intstatus;
public: Interrupts(Params * p) : SimObject(p), cpu(NULL)
Interrupts() {
{ memset(interrupts, 0, sizeof(interrupts));
memset(interrupts, 0, sizeof(interrupts)); intstatus = 0;
intstatus = 0; newInfoSet = false;
newInfoSet = false; }
}
void post(int int_num, int index) void
{ setCPU(BaseCPU * _cpu)
DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); {
cpu = _cpu;
}
if (int_num < 0 || int_num >= NumInterruptLevels) void
panic("int_num out of bounds\n"); post(int int_num, int index)
{
DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
if (index < 0 || index >= sizeof(uint64_t) * 8) if (int_num < 0 || int_num >= NumInterruptLevels)
panic("int_num out of bounds\n"); panic("int_num out of bounds\n");
interrupts[int_num] |= 1 << index; if (index < 0 || index >= (int)sizeof(uint64_t) * 8)
intstatus |= (ULL(1) << int_num); panic("int_num out of bounds\n");
}
void clear(int int_num, int index) interrupts[int_num] |= 1 << index;
{ intstatus |= (ULL(1) << int_num);
DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); }
if (int_num < 0 || int_num >= TheISA::NumInterruptLevels) void
panic("int_num out of bounds\n"); clear(int int_num, int index)
{
DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
if (index < 0 || index >= sizeof(uint64_t) * 8) if (int_num < 0 || int_num >= NumInterruptLevels)
panic("int_num out of bounds\n"); panic("int_num out of bounds\n");
interrupts[int_num] &= ~(1 << index); if (index < 0 || index >= (int)sizeof(uint64_t) * 8)
if (interrupts[int_num] == 0) panic("int_num out of bounds\n");
intstatus &= ~(ULL(1) << int_num);
}
void clear_all() interrupts[int_num] &= ~(1 << index);
{ if (interrupts[int_num] == 0)
DPRINTF(Interrupt, "Interrupts all cleared\n"); intstatus &= ~(ULL(1) << int_num);
}
memset(interrupts, 0, sizeof(interrupts)); void
intstatus = 0; clearAll()
} {
DPRINTF(Interrupt, "Interrupts all cleared\n");
void serialize(std::ostream &os) memset(interrupts, 0, sizeof(interrupts));
{ intstatus = 0;
SERIALIZE_ARRAY(interrupts, NumInterruptLevels); }
SERIALIZE_SCALAR(intstatus);
}
void unserialize(Checkpoint *cp, const std::string &section) void
{ serialize(std::ostream &os)
UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels); {
UNSERIALIZE_SCALAR(intstatus); SERIALIZE_ARRAY(interrupts, NumInterruptLevels);
} SERIALIZE_SCALAR(intstatus);
}
bool check_interrupts(ThreadContext * tc) const void
{ unserialize(Checkpoint *cp, const std::string &section)
return (intstatus != 0) && !(tc->readPC() & 0x3); {
} UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels);
UNSERIALIZE_SCALAR(intstatus);
}
Fault getInterrupt(ThreadContext * tc) bool
{ checkInterrupts(ThreadContext *tc) const
int ipl = 0; {
int summary = 0; return (intstatus != 0) && !(tc->readPC() & 0x3);
}
if (tc->readMiscRegNoEffect(IPR_ASTRR)) Fault
panic("asynchronous traps not implemented\n"); getInterrupt(ThreadContext *tc)
{
int ipl = 0;
int summary = 0;
if (tc->readMiscRegNoEffect(IPR_SIRR)) { if (tc->readMiscRegNoEffect(IPR_ASTRR))
for (int i = INTLEVEL_SOFTWARE_MIN; panic("asynchronous traps not implemented\n");
i < INTLEVEL_SOFTWARE_MAX; i++) {
if (tc->readMiscRegNoEffect(IPR_SIRR) & (ULL(1) << i)) { if (tc->readMiscRegNoEffect(IPR_SIRR)) {
// See table 4-19 of 21164 hardware reference for (int i = INTLEVEL_SOFTWARE_MIN;
ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1; i < INTLEVEL_SOFTWARE_MAX; i++) {
summary |= (ULL(1) << i); if (tc->readMiscRegNoEffect(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; uint64_t interrupts = intstatus;
if (interrupts) { if (interrupts) {
for (int i = INTLEVEL_EXTERNAL_MIN; for (int i = INTLEVEL_EXTERNAL_MIN;
i < INTLEVEL_EXTERNAL_MAX; i++) { i < INTLEVEL_EXTERNAL_MAX; i++) {
if (interrupts & (ULL(1) << i)) { if (interrupts & (ULL(1) << i)) {
// See table 4-19 of 21164 hardware reference // See table 4-19 of 21164 hardware reference
ipl = i; ipl = i;
summary |= (ULL(1) << i); summary |= (ULL(1) << i);
}
} }
} }
if (ipl && ipl > tc->readMiscRegNoEffect(IPR_IPLR)) {
newIpl = ipl;
newSummary = summary;
newInfoSet = true;
DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
tc->readMiscRegNoEffect(IPR_IPLR), ipl, summary);
return new InterruptFault;
} else {
return NoFault;
}
} }
void updateIntrInfo(ThreadContext *tc) if (ipl && ipl > tc->readMiscRegNoEffect(IPR_IPLR)) {
{ newIpl = ipl;
assert(newInfoSet); newSummary = summary;
tc->setMiscRegNoEffect(IPR_ISR, newSummary); newInfoSet = true;
tc->setMiscRegNoEffect(IPR_INTID, newIpl); DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
newInfoSet = false; tc->readMiscRegNoEffect(IPR_IPLR), ipl, summary);
return new InterruptFault;
} else {
return NoFault;
} }
}
uint64_t get_vec(int int_num) void
{ updateIntrInfo(ThreadContext *tc)
panic("Shouldn't be called for Alpha\n"); {
M5_DUMMY_RETURN assert(newInfoSet);
} tc->setMiscRegNoEffect(IPR_ISR, newSummary);
tc->setMiscRegNoEffect(IPR_INTID, newIpl);
newInfoSet = false;
}
};
private: } // namespace AlphaISA
bool newInfoSet;
int newIpl;
int newSummary;
};
}
#endif #endif // __ARCH_ALPHA_INTERRUPT_HH__

View file

@ -30,36 +30,45 @@
* Kevin Lim * Kevin Lim
*/ */
#include <cstring>
#include "arch/alpha/isa_traits.hh" #include "arch/alpha/isa_traits.hh"
#include "arch/alpha/intregfile.hh" #include "arch/alpha/intregfile.hh"
#include "sim/serialize.hh" #include "sim/serialize.hh"
namespace AlphaISA namespace AlphaISA {
{
#if FULL_SYSTEM #if FULL_SYSTEM
const int reg_redir[AlphaISA::NumIntRegs] = { const int reg_redir[NumIntRegs] = {
/* 0 */ 0, 1, 2, 3, 4, 5, 6, 7, /* 0 */ 0, 1, 2, 3, 4, 5, 6, 7,
/* 8 */ 32, 33, 34, 35, 36, 37, 38, 15, /* 8 */ 32, 33, 34, 35, 36, 37, 38, 15,
/* 16 */ 16, 17, 18, 19, 20, 21, 22, 23, /* 16 */ 16, 17, 18, 19, 20, 21, 22, 23,
/* 24 */ 24, 39, 26, 27, 28, 29, 30, 31 }; /* 24 */ 24, 39, 26, 27, 28, 29, 30, 31 };
#else #else
const int reg_redir[AlphaISA::NumIntRegs] = { const int reg_redir[NumIntRegs] = {
/* 0 */ 0, 1, 2, 3, 4, 5, 6, 7, /* 0 */ 0, 1, 2, 3, 4, 5, 6, 7,
/* 8 */ 8, 9, 10, 11, 12, 13, 14, 15, /* 8 */ 8, 9, 10, 11, 12, 13, 14, 15,
/* 16 */ 16, 17, 18, 19, 20, 21, 22, 23, /* 16 */ 16, 17, 18, 19, 20, 21, 22, 23,
/* 24 */ 24, 25, 26, 27, 28, 29, 30, 31 }; /* 24 */ 24, 25, 26, 27, 28, 29, 30, 31 };
#endif #endif
void void
IntRegFile::serialize(std::ostream &os) IntRegFile::clear()
{ {
SERIALIZE_ARRAY(regs, NumIntRegs); std::memset(regs, 0, sizeof(regs));
}
void
IntRegFile::unserialize(Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_ARRAY(regs, NumIntRegs);
}
} }
void
IntRegFile::serialize(std::ostream &os)
{
SERIALIZE_ARRAY(regs, NumIntRegs);
}
void
IntRegFile::unserialize(Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_ARRAY(regs, NumIntRegs);
}
} // namespace AlphaISA

View file

@ -32,47 +32,42 @@
#ifndef __ARCH_ALPHA_INTREGFILE_HH__ #ifndef __ARCH_ALPHA_INTREGFILE_HH__
#define __ARCH_ALPHA_INTREGFILE_HH__ #define __ARCH_ALPHA_INTREGFILE_HH__
#include "arch/alpha/types.hh" #include <iosfwd>
#include <string>
#include <iostream> #include "arch/alpha/types.hh"
#include <cstring>
class Checkpoint; class Checkpoint;
namespace AlphaISA namespace AlphaISA {
// redirected register map, really only used for the full system case.
extern const int reg_redir[NumIntRegs];
class IntRegFile
{ {
static inline std::string getIntRegName(RegIndex) protected:
IntReg regs[NumIntRegs];
public:
IntReg
readReg(int intReg)
{ {
return ""; return regs[intReg];
} }
// redirected register map, really only used for the full system case. void
extern const int reg_redir[NumIntRegs]; setReg(int intReg, const IntReg &val)
class IntRegFile
{ {
protected: regs[intReg] = val;
IntReg regs[NumIntRegs]; }
public: void clear();
IntReg readReg(int intReg) void serialize(std::ostream &os);
{ void unserialize(Checkpoint *cp, const std::string &section);
return regs[intReg]; };
}
void setReg(int intReg, const IntReg &val) } // namespace AlphaISA
{
regs[intReg] = val;
}
void serialize(std::ostream &os); #endif // __ARCH_ALPHA_INTREGFILE_HH__
void unserialize(Checkpoint *cp, const std::string &section);
void clear()
{ std::memset(regs, 0, sizeof(regs)); }
};
}
#endif

View file

@ -28,113 +28,115 @@
* Authors: Gabe Black * Authors: Gabe Black
*/ */
#include <assert.h> #include <cassert>
#include <string.h> #include <cstring>
#include "arch/alpha/ipr.hh" #include "arch/alpha/ipr.hh"
namespace AlphaISA 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()
{ {
md_ipr_names MiscRegIndexToIpr[NumInternalProcRegs] = static bool initialized = false;
{ if (initialized)
//Write only return;
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 memset(IprToMiscRegIndex, -1, MaxInternalProcRegs * sizeof(int));
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 for (int x = 0; x < NumInternalProcRegs; x++)
RAW_IPR_ITB_TAG, // ITLB tag register IprToMiscRegIndex[MiscRegIndexToIpr[x]] = x;
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;
}
} }
} // namespace AlphaISA

View file

@ -32,206 +32,208 @@
#ifndef __ARCH_ALPHA_IPR_HH__ #ifndef __ARCH_ALPHA_IPR_HH__
#define __ARCH_ALPHA_IPR_HH__ #define __ARCH_ALPHA_IPR_HH__
namespace AlphaISA namespace AlphaISA {
////////////////////////////////////////////////////////////////////////
//
// Internal Processor Reigsters
//
enum md_ipr_names {
RAW_IPR_ISR = 0x100, // interrupt summary
RAW_IPR_ITB_TAG = 0x101, // ITLB tag
RAW_IPR_ITB_PTE = 0x102, // ITLB page table entry
RAW_IPR_ITB_ASN = 0x103, // ITLB address space
RAW_IPR_ITB_PTE_TEMP = 0x104, // ITLB page table entry temp
RAW_IPR_ITB_IA = 0x105, // ITLB invalidate all
RAW_IPR_ITB_IAP = 0x106, // ITLB invalidate all process
RAW_IPR_ITB_IS = 0x107, // ITLB invalidate select
RAW_IPR_SIRR = 0x108, // software interrupt request
RAW_IPR_ASTRR = 0x109, // asynchronous system trap request
RAW_IPR_ASTER = 0x10a, // asynchronous system trap enable
RAW_IPR_EXC_ADDR = 0x10b, // exception address
RAW_IPR_EXC_SUM = 0x10c, // exception summary
RAW_IPR_EXC_MASK = 0x10d, // exception mask
RAW_IPR_PAL_BASE = 0x10e, // PAL base address
RAW_IPR_ICM = 0x10f, // instruction current mode
RAW_IPR_IPLR = 0x110, // interrupt priority level
RAW_IPR_INTID = 0x111, // interrupt ID
RAW_IPR_IFAULT_VA_FORM = 0x112, // formatted faulting virtual addr
RAW_IPR_IVPTBR = 0x113, // virtual page table base
RAW_IPR_HWINT_CLR = 0x115, // H/W interrupt clear
RAW_IPR_SL_XMIT = 0x116, // serial line transmit
RAW_IPR_SL_RCV = 0x117, // serial line receive
RAW_IPR_ICSR = 0x118, // instruction control and status
RAW_IPR_IC_FLUSH = 0x119, // instruction cache flush control
RAW_IPR_IC_PERR_STAT = 0x11a, // inst cache parity error status
RAW_IPR_PMCTR = 0x11c, // performance counter
// 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
RAW_IPR_DTB_CM = 0x201, // DTLB current mode
RAW_IPR_DTB_TAG = 0x202, // DTLB tag
RAW_IPR_DTB_PTE = 0x203, // DTLB page table entry
RAW_IPR_DTB_PTE_TEMP = 0x204, // DTLB page table entry temporary
RAW_IPR_MM_STAT = 0x205, // data MMU fault status
RAW_IPR_VA = 0x206, // fault virtual address
RAW_IPR_VA_FORM = 0x207, // formatted virtual address
RAW_IPR_MVPTBR = 0x208, // MTU virtual page table base
RAW_IPR_DTB_IAP = 0x209, // DTLB invalidate all process
RAW_IPR_DTB_IA = 0x20a, // DTLB invalidate all
RAW_IPR_DTB_IS = 0x20b, // DTLB invalidate single
RAW_IPR_ALT_MODE = 0x20c, // alternate mode
RAW_IPR_CC = 0x20d, // cycle counter
RAW_IPR_CC_CTL = 0x20e, // cycle counter control
RAW_IPR_MCSR = 0x20f, // MTU control
RAW_IPR_DC_FLUSH = 0x210,
RAW_IPR_DC_PERR_STAT = 0x212, // Dcache parity error status
RAW_IPR_DC_TEST_CTL = 0x213, // Dcache test tag control
RAW_IPR_DC_TEST_TAG = 0x214, // Dcache test tag
RAW_IPR_DC_TEST_TAG_TEMP = 0x215, // Dcache test tag temporary
RAW_IPR_DC_MODE = 0x216, // Dcache mode
RAW_IPR_MAF_MODE = 0x217, // miss address file mode
MaxInternalProcRegs // number of IPRs
};
enum MiscRegIpr
{ {
//////////////////////////////////////////////////////////////////////// //Write only
// MinWriteOnlyIpr,
// Internal Processor Reigsters IPR_HWINT_CLR = MinWriteOnlyIpr,
// IPR_SL_XMIT,
enum md_ipr_names IPR_DC_FLUSH,
{ IPR_IC_FLUSH,
RAW_IPR_ISR = 0x100, // interrupt summary register IPR_ALT_MODE,
RAW_IPR_ITB_TAG = 0x101, // ITLB tag register IPR_DTB_IA,
RAW_IPR_ITB_PTE = 0x102, // ITLB page table entry register IPR_DTB_IAP,
RAW_IPR_ITB_ASN = 0x103, // ITLB address space register IPR_ITB_IA,
RAW_IPR_ITB_PTE_TEMP = 0x104, // ITLB page table entry temp register MaxWriteOnlyIpr,
RAW_IPR_ITB_IA = 0x105, // ITLB invalidate all register IPR_ITB_IAP = MaxWriteOnlyIpr,
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... //Read only
// register meanings gleaned from osfpal.s source code MinReadOnlyIpr,
RAW_IPR_PALtemp0 = 0x140, // local scratch IPR_INTID = MinReadOnlyIpr,
RAW_IPR_PALtemp1 = 0x141, // local scratch IPR_SL_RCV,
RAW_IPR_PALtemp2 = 0x142, // entUna IPR_MM_STAT,
RAW_IPR_PALtemp3 = 0x143, // CPU specific impure area pointer IPR_ITB_PTE_TEMP,
RAW_IPR_PALtemp4 = 0x144, // memory management temp MaxReadOnlyIpr,
RAW_IPR_PALtemp5 = 0x145, // memory management temp IPR_DTB_PTE_TEMP = MaxReadOnlyIpr,
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 IPR_ISR,
RAW_IPR_DTB_CM = 0x201, // DTLB current mode register IPR_ITB_TAG,
RAW_IPR_DTB_TAG = 0x202, // DTLB tag register IPR_ITB_PTE,
RAW_IPR_DTB_PTE = 0x203, // DTLB page table entry register IPR_ITB_ASN,
RAW_IPR_DTB_PTE_TEMP = 0x204, // DTLB page table entry temporary register 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,
RAW_IPR_MM_STAT = 0x205, // data MMU fault status register // PAL temporary registers...
RAW_IPR_VA = 0x206, // fault virtual address register // register meanings gleaned from osfpal.s source code
RAW_IPR_VA_FORM = 0x207, // formatted virtual address register IPR_PALtemp0,
RAW_IPR_MVPTBR = 0x208, // MTU virtual page table base register IPR_PALtemp1,
RAW_IPR_DTB_IAP = 0x209, // DTLB invalidate all process register IPR_PALtemp2,
RAW_IPR_DTB_IA = 0x20a, // DTLB invalidate all register IPR_PALtemp3,
RAW_IPR_DTB_IS = 0x20b, // DTLB invalidate single register IPR_PALtemp4,
RAW_IPR_ALT_MODE = 0x20c, // alternate mode register IPR_PALtemp5,
RAW_IPR_CC = 0x20d, // cycle counter register IPR_PALtemp6,
RAW_IPR_CC_CTL = 0x20e, // cycle counter control register IPR_PALtemp7,
RAW_IPR_MCSR = 0x20f, // MTU control register 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,
RAW_IPR_DC_FLUSH = 0x210, IPR_DTB_ASN,
RAW_IPR_DC_PERR_STAT = 0x212, // Dcache parity error status register IPR_DTB_CM,
RAW_IPR_DC_TEST_CTL = 0x213, // Dcache test tag control register IPR_DTB_TAG,
RAW_IPR_DC_TEST_TAG = 0x214, // Dcache test tag register IPR_DTB_PTE,
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 IPR_VA,
}; IPR_VA_FORM,
IPR_MVPTBR,
IPR_DTB_IS,
IPR_CC,
IPR_CC_CTL,
IPR_MCSR,
enum MiscRegIpr IPR_DC_PERR_STAT,
{ IPR_DC_TEST_CTL,
//Write only IPR_DC_TEST_TAG,
MinWriteOnlyIpr, IPR_DC_TEST_TAG_TEMP,
IPR_HWINT_CLR = MinWriteOnlyIpr, IPR_DC_MODE,
IPR_SL_XMIT, IPR_MAF_MODE,
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 NumInternalProcRegs // number of IPR registers
MinReadOnlyIpr, };
IPR_INTID = MinReadOnlyIpr,
IPR_SL_RCV,
IPR_MM_STAT,
IPR_ITB_PTE_TEMP,
MaxReadOnlyIpr,
IPR_DTB_PTE_TEMP = MaxReadOnlyIpr,
IPR_ISR, inline bool
IPR_ITB_TAG, IprIsWritable(int index)
IPR_ITB_PTE, {
IPR_ITB_ASN, return index < MinReadOnlyIpr || index > MaxReadOnlyIpr;
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 inline bool
IprIsReadable(int index)
{
return index < MinWriteOnlyIpr || index > MaxWriteOnlyIpr;
}
extern md_ipr_names MiscRegIndexToIpr[NumInternalProcRegs];
extern int IprToMiscRegIndex[MaxInternalProcRegs];
void initializeIprTable();
} // namespace AlphaISA
#endif // __ARCH_ALPHA_IPR_HH__

View file

@ -638,7 +638,7 @@ decode OPCODE default Unknown::unknown() {
/* Rb is a fake dependency so here is a fun way to get /* Rb is a fake dependency so here is a fun way to get
* the parser to understand that. * the parser to understand that.
*/ */
Ra = xc->readMiscReg(AlphaISA::IPR_CC) + (Rb & 0); Ra = xc->readMiscReg(IPR_CC) + (Rb & 0);
#else #else
Ra = curTick; Ra = curTick;
@ -690,7 +690,7 @@ decode OPCODE default Unknown::unknown() {
0x00: CallPal::call_pal({{ 0x00: CallPal::call_pal({{
if (!palValid || if (!palValid ||
(palPriv (palPriv
&& xc->readMiscReg(AlphaISA::IPR_ICM) != AlphaISA::mode_kernel)) { && xc->readMiscReg(IPR_ICM) != mode_kernel)) {
// invalid pal function code, or attempt to do privileged // invalid pal function code, or attempt to do privileged
// PAL call in non-kernel mode // PAL call in non-kernel mode
fault = new UnimplementedOpcodeFault; fault = new UnimplementedOpcodeFault;
@ -701,8 +701,8 @@ decode OPCODE default Unknown::unknown() {
bool dopal = xc->simPalCheck(palFunc); bool dopal = xc->simPalCheck(palFunc);
if (dopal) { if (dopal) {
xc->setMiscReg(AlphaISA::IPR_EXC_ADDR, NPC); xc->setMiscReg(IPR_EXC_ADDR, NPC);
NPC = xc->readMiscReg(AlphaISA::IPR_PAL_BASE) + palOffset; NPC = xc->readMiscReg(IPR_PAL_BASE) + palOffset;
} }
} }
}}, IsNonSpeculative); }}, IsNonSpeculative);
@ -783,14 +783,19 @@ decode OPCODE default Unknown::unknown() {
} }
} }
format BasicOperate { 0x1e: decode PALMODE {
0x1e: decode PALMODE { 0: OpcdecFault::hw_rei();
0: OpcdecFault::hw_rei(); format BasicOperate {
1:hw_rei({{ xc->hwrei(); }}, IsSerializing, IsSerializeBefore); 1: hw_rei({{ xc->hwrei(); }}, IsSerializing, IsSerializeBefore);
} }
}
#endif
format BasicOperate {
// M5 special opcodes use the reserved 0x01 opcode space // M5 special opcodes use the reserved 0x01 opcode space
0x01: decode M5FUNC { 0x01: decode M5FUNC {
#if FULL_SYSTEM
0x00: arm({{ 0x00: arm({{
PseudoInst::arm(xc->tcBase()); PseudoInst::arm(xc->tcBase());
}}, IsNonSpeculative); }}, IsNonSpeculative);
@ -806,22 +811,34 @@ decode OPCODE default Unknown::unknown() {
0x04: quiesceTime({{ 0x04: quiesceTime({{
R0 = PseudoInst::quiesceTime(xc->tcBase()); R0 = PseudoInst::quiesceTime(xc->tcBase());
}}, IsNonSpeculative, IsUnverifiable); }}, IsNonSpeculative, IsUnverifiable);
0x10: ivlb({{ #endif
warn_once("Obsolete M5 instruction ivlb encountered.\n"); 0x07: rpns({{
R0 = PseudoInst::rpns(xc->tcBase());
}}, IsNonSpeculative, IsUnverifiable);
0x09: wakeCPU({{
PseudoInst::wakeCPU(xc->tcBase(), R16);
}}, IsNonSpeculative, IsUnverifiable);
0x10: deprecated_ivlb({{
warn_once("Obsolete M5 ivlb instruction encountered.\n");
}}); }});
0x11: ivle({{ 0x11: deprecated_ivle({{
warn_once("Obsolete M5 instruction ivlb encountered.\n"); warn_once("Obsolete M5 ivlb instruction encountered.\n");
}}); }});
0x20: m5exit_old({{ 0x20: deprecated_exit ({{
PseudoInst::m5exit_old(xc->tcBase()); warn_once("deprecated M5 exit instruction encountered.\n");
PseudoInst::m5exit(xc->tcBase(), 0);
}}, No_OpClass, IsNonSpeculative); }}, No_OpClass, IsNonSpeculative);
0x21: m5exit({{ 0x21: m5exit({{
PseudoInst::m5exit(xc->tcBase(), R16); PseudoInst::m5exit(xc->tcBase(), R16);
}}, No_OpClass, IsNonSpeculative); }}, No_OpClass, IsNonSpeculative);
#if FULL_SYSTEM
0x31: loadsymbol({{ 0x31: loadsymbol({{
PseudoInst::loadsymbol(xc->tcBase()); PseudoInst::loadsymbol(xc->tcBase());
}}, No_OpClass, IsNonSpeculative); }}, No_OpClass, IsNonSpeculative);
0x30: initparam({{ Ra = xc->tcBase()->getCpuPtr()->system->init_param; }}); 0x30: initparam({{
Ra = xc->tcBase()->getCpuPtr()->system->init_param;
}});
#endif
0x40: resetstats({{ 0x40: resetstats({{
PseudoInst::resetstats(xc->tcBase(), R16, R17); PseudoInst::resetstats(xc->tcBase(), R16, R17);
}}, IsNonSpeculative); }}, IsNonSpeculative);
@ -834,28 +851,93 @@ decode OPCODE default Unknown::unknown() {
0x43: m5checkpoint({{ 0x43: m5checkpoint({{
PseudoInst::m5checkpoint(xc->tcBase(), R16, R17); PseudoInst::m5checkpoint(xc->tcBase(), R16, R17);
}}, IsNonSpeculative); }}, IsNonSpeculative);
#if FULL_SYSTEM
0x50: m5readfile({{ 0x50: m5readfile({{
R0 = PseudoInst::readfile(xc->tcBase(), R16, R17, R18); R0 = PseudoInst::readfile(xc->tcBase(), R16, R17, R18);
}}, IsNonSpeculative); }}, IsNonSpeculative);
#endif
0x51: m5break({{ 0x51: m5break({{
PseudoInst::debugbreak(xc->tcBase()); PseudoInst::debugbreak(xc->tcBase());
}}, IsNonSpeculative); }}, IsNonSpeculative);
0x52: m5switchcpu({{ 0x52: m5switchcpu({{
PseudoInst::switchcpu(xc->tcBase()); PseudoInst::switchcpu(xc->tcBase());
}}, IsNonSpeculative); }}, IsNonSpeculative);
#if FULL_SYSTEM
0x53: m5addsymbol({{ 0x53: m5addsymbol({{
PseudoInst::addsymbol(xc->tcBase(), R16, R17); PseudoInst::addsymbol(xc->tcBase(), R16, R17);
}}, IsNonSpeculative); }}, IsNonSpeculative);
#endif
0x54: m5panic({{ 0x54: m5panic({{
panic("M5 panic instruction called at pc=%#x.", xc->readPC()); panic("M5 panic instruction called at pc=%#x.", xc->readPC());
}}, IsNonSpeculative); }}, IsNonSpeculative);
0x55: m5anBegin({{ #define CPANN(lbl) CPA::cpa()->lbl(xc->tcBase())
PseudoInst::anBegin(xc->tcBase(), R16); 0x55: decode RA {
0x00: m5a_old({{
panic("Deprecated M5 annotate instruction executed at pc=%#x\n",
xc->readPC());
}}, IsNonSpeculative);
0x01: m5a_bsm({{
CPANN(swSmBegin);
}}, IsNonSpeculative);
0x02: m5a_esm({{
CPANN(swSmEnd);
}}, IsNonSpeculative);
0x03: m5a_begin({{
CPANN(swExplictBegin);
}}, IsNonSpeculative);
0x04: m5a_end({{
CPANN(swEnd);
}}, IsNonSpeculative);
0x06: m5a_q({{
CPANN(swQ);
}}, IsNonSpeculative);
0x07: m5a_dq({{
CPANN(swDq);
}}, IsNonSpeculative);
0x08: m5a_wf({{
CPANN(swWf);
}}, IsNonSpeculative);
0x09: m5a_we({{
CPANN(swWe);
}}, IsNonSpeculative);
0x0C: m5a_sq({{
CPANN(swSq);
}}, IsNonSpeculative);
0x0D: m5a_aq({{
CPANN(swAq);
}}, IsNonSpeculative);
0x0E: m5a_pq({{
CPANN(swPq);
}}, IsNonSpeculative);
0x0F: m5a_l({{
CPANN(swLink);
}}, IsNonSpeculative);
0x10: m5a_identify({{
CPANN(swIdentify);
}}, IsNonSpeculative);
0x11: m5a_getid({{
R0 = CPANN(swGetId);
}}, IsNonSpeculative);
0x13: m5a_scl({{
CPANN(swSyscallLink);
}}, IsNonSpeculative);
0x14: m5a_rq({{
CPANN(swRq);
}}, IsNonSpeculative);
} // M5 Annotate Operations
#undef CPANN
0x56: m5reserved2({{
warn("M5 reserved opcode ignored");
}}, IsNonSpeculative); }}, IsNonSpeculative);
0x56: m5anWait({{ 0x57: m5reserved3({{
PseudoInst::anWait(xc->tcBase(), R16, R17); warn("M5 reserved opcode ignored");
}}, IsNonSpeculative);
0x58: m5reserved4({{
warn("M5 reserved opcode ignored");
}}, IsNonSpeculative);
0x59: m5reserved5({{
warn("M5 reserved opcode ignored");
}}, IsNonSpeculative); }}, IsNonSpeculative);
} }
} }
#endif
} }

View file

@ -46,7 +46,7 @@ output exec {{
inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
{ {
Fault fault = NoFault; // dummy... this ipr access should not fault Fault fault = NoFault; // dummy... this ipr access should not fault
if (!EV5::ICSR_FPE(xc->readMiscReg(AlphaISA::IPR_ICSR))) { if (!ICSR_FPE(xc->readMiscReg(IPR_ICSR))) {
fault = new FloatEnableFault; fault = new FloatEnableFault;
} }
return fault; return fault;
@ -229,7 +229,7 @@ def template FloatingPointExecute {{
%(code)s; %(code)s;
} else { } else {
m5_fesetround(getC99RoundingMode( m5_fesetround(getC99RoundingMode(
xc->readMiscRegNoEffect(AlphaISA::MISCREG_FPCR))); xc->readMiscRegNoEffect(MISCREG_FPCR)));
%(code)s; %(code)s;
m5_fesetround(M5_FE_TONEAREST); m5_fesetround(M5_FE_TONEAREST);
} }

View file

@ -68,9 +68,8 @@ using namespace AlphaISA;
output exec {{ output exec {{
#include <math.h> #include <math.h>
#if FULL_SYSTEM #include "base/cp_annotate.hh"
#include "sim/pseudo_inst.hh" #include "sim/pseudo_inst.hh"
#endif
#include "arch/alpha/ipr.hh" #include "arch/alpha/ipr.hh"
#include "base/fenv.hh" #include "base/fenv.hh"
#include "config/ss_compatible_fp.hh" #include "config/ss_compatible_fp.hh"
@ -173,11 +172,11 @@ def operands {{
# Int regs default to unsigned, but code should not count on this. # Int regs default to unsigned, but code should not count on this.
# For clarity, descriptions that depend on unsigned behavior should # For clarity, descriptions that depend on unsigned behavior should
# explicitly specify '.uq'. # explicitly specify '.uq'.
'Ra': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RA] : RA', 'Ra': ('IntReg', 'uq', 'PALMODE ? reg_redir[RA] : RA',
'IsInteger', 1), 'IsInteger', 1),
'Rb': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RB] : RB', 'Rb': ('IntReg', 'uq', 'PALMODE ? reg_redir[RB] : RB',
'IsInteger', 2), 'IsInteger', 2),
'Rc': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RC] : RC', 'Rc': ('IntReg', 'uq', 'PALMODE ? reg_redir[RC] : RC',
'IsInteger', 3), 'IsInteger', 3),
'Fa': ('FloatReg', 'df', 'FA', 'IsFloating', 1), 'Fa': ('FloatReg', 'df', 'FA', 'IsFloating', 1),
'Fb': ('FloatReg', 'df', 'FB', 'IsFloating', 2), 'Fb': ('FloatReg', 'df', 'FB', 'IsFloating', 2),

View file

@ -43,7 +43,7 @@ output header {{
protected: protected:
/// Memory request flags. See mem_req_base.hh. /// Memory request flags. See mem_req_base.hh.
unsigned memAccessFlags; Request::Flags memAccessFlags;
/// Pointer to EAComp object. /// Pointer to EAComp object.
const StaticInstPtr eaCompPtr; const StaticInstPtr eaCompPtr;
/// Pointer to MemAcc object. /// Pointer to MemAcc object.
@ -54,7 +54,7 @@ output header {{
StaticInstPtr _eaCompPtr = nullStaticInstPtr, StaticInstPtr _eaCompPtr = nullStaticInstPtr,
StaticInstPtr _memAccPtr = nullStaticInstPtr) StaticInstPtr _memAccPtr = nullStaticInstPtr)
: AlphaStaticInst(mnem, _machInst, __opClass), : AlphaStaticInst(mnem, _machInst, __opClass),
memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr) eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr)
{ {
} }
@ -677,6 +677,7 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
inst_flags) inst_flags)
if mem_flags: if mem_flags:
mem_flags = [ 'Request::%s' % flag for flag in mem_flags ]
s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';' s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
iop.constructor += s iop.constructor += s
memacc_iop.constructor += s memacc_iop.constructor += s

View file

@ -174,11 +174,11 @@ output decoder {{
: Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr), : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
disp(HW_LDST_DISP) disp(HW_LDST_DISP)
{ {
memAccessFlags = 0; memAccessFlags.clear();
if (HW_LDST_PHYS) memAccessFlags |= PHYSICAL; if (HW_LDST_PHYS) memAccessFlags.set(Request::PHYSICAL);
if (HW_LDST_ALT) memAccessFlags |= ALTMODE; if (HW_LDST_ALT) memAccessFlags.set(Request::ALTMODE);
if (HW_LDST_VPTE) memAccessFlags |= VPTE; if (HW_LDST_VPTE) memAccessFlags.set(Request::VPTE);
if (HW_LDST_LOCK) memAccessFlags |= LOCKED; if (HW_LDST_LOCK) memAccessFlags.set(Request::LOCKED);
} }
std::string std::string

View file

@ -42,142 +42,134 @@ namespace LittleEndianGuest {}
class StaticInstPtr; class StaticInstPtr;
namespace AlphaISA namespace AlphaISA {
{
using namespace LittleEndianGuest;
using AlphaISAInst::MaxInstSrcRegs;
using AlphaISAInst::MaxInstDestRegs;
// These enumerate all the registers for dependence tracking. using namespace LittleEndianGuest;
enum DependenceTags { using AlphaISAInst::MaxInstSrcRegs;
// 0..31 are the integer regs 0..31 using AlphaISAInst::MaxInstDestRegs;
// 32..63 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag)
FP_Base_DepTag = 40,
Ctrl_Base_DepTag = 72
};
StaticInstPtr decodeInst(ExtMachInst);
// Alpha Does NOT have a delay slot
#define ISA_HAS_DELAY_SLOT 0
const Addr PageShift = 13;
const Addr PageBytes = ULL(1) << PageShift;
const Addr PageMask = ~(PageBytes - 1);
const Addr PageOffset = PageBytes - 1;
////////////////////////////////////////////////////////////////////////
//
// Translation stuff
//
const Addr PteShift = 3;
const Addr NPtePageShift = PageShift - PteShift;
const Addr NPtePage = ULL(1) << NPtePageShift;
const Addr PteMask = NPtePage - 1;
// User Virtual
const Addr USegBase = ULL(0x0);
const Addr USegEnd = ULL(0x000003ffffffffff);
// Kernel Direct Mapped
const Addr K0SegBase = ULL(0xfffffc0000000000);
const Addr K0SegEnd = ULL(0xfffffdffffffffff);
// Kernel Virtual
const Addr K1SegBase = ULL(0xfffffe0000000000);
const Addr K1SegEnd = ULL(0xffffffffffffffff);
// For loading... XXX This maybe could be USegEnd?? --ali
const Addr LoadAddrMask = ULL(0xffffffffff);
#if FULL_SYSTEM
////////////////////////////////////////////////////////////////////////
//
// Interrupt levels
//
enum InterruptLevels
{
INTLEVEL_SOFTWARE_MIN = 4,
INTLEVEL_SOFTWARE_MAX = 19,
INTLEVEL_EXTERNAL_MIN = 20,
INTLEVEL_EXTERNAL_MAX = 34,
INTLEVEL_IRQ0 = 20,
INTLEVEL_IRQ1 = 21,
INTINDEX_ETHERNET = 0,
INTINDEX_SCSI = 1,
INTLEVEL_IRQ2 = 22,
INTLEVEL_IRQ3 = 23,
INTLEVEL_SERIAL = 33,
NumInterruptLevels = INTLEVEL_EXTERNAL_MAX
};
#endif
// EV5 modes
enum mode_type
{
mode_kernel = 0, // kernel
mode_executive = 1, // executive (unused by unix)
mode_supervisor = 2, // supervisor (unused by unix)
mode_user = 3, // user mode
mode_number // number of modes
};
// Constants Related to the number of registers
const int NumIntArchRegs = 32;
const int NumPALShadowRegs = 8;
const int NumFloatArchRegs = 32;
// @todo: Figure out what this number really should be.
const int NumMiscArchRegs = 77;
const int NumIntRegs = NumIntArchRegs + NumPALShadowRegs;
const int NumFloatRegs = NumFloatArchRegs;
const int NumMiscRegs = NumMiscArchRegs;
const int TotalNumRegs = NumIntRegs + NumFloatRegs +
NumMiscRegs + NumInternalProcRegs;
const int TotalDataRegs = NumIntRegs + NumFloatRegs;
// semantically meaningful register indices
const int ZeroReg = 31; // architecturally meaningful
// the rest of these depend on the ABI
const int StackPointerReg = 30;
const int GlobalPointerReg = 29;
const int ProcedureValueReg = 27;
const int ReturnAddressReg = 26;
const int ReturnValueReg = 0;
const int FramePointerReg = 15;
const int ArgumentReg[] = {16, 17, 18, 19, 20, 21};
const int NumArgumentRegs = sizeof(ArgumentReg) / sizeof(const int);
const int SyscallNumReg = ReturnValueReg;
const int SyscallPseudoReturnReg = ArgumentReg[4];
const int SyscallSuccessReg = 19;
const int LogVMPageSize = 13; // 8K bytes
const int VMPageSize = (1 << LogVMPageSize);
const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned
const int MachineBytes = 8;
const int WordBytes = 4;
const int HalfwordBytes = 2;
const int ByteBytes = 1;
// return a no-op instruction... used for instruction fetch faults
// Alpha UNOP (ldq_u r31,0(r0))
const ExtMachInst NoopMachInst = 0x2ffe0000;
// These enumerate all the registers for dependence tracking.
enum DependenceTags {
// 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
}; };
StaticInstPtr decodeInst(ExtMachInst);
// Alpha Does NOT have a delay slot
#define ISA_HAS_DELAY_SLOT 0
const Addr PageShift = 13;
const Addr PageBytes = ULL(1) << PageShift;
const Addr PageMask = ~(PageBytes - 1);
const Addr PageOffset = PageBytes - 1;
////////////////////////////////////////////////////////////////////////
//
// Translation stuff
//
const Addr PteShift = 3;
const Addr NPtePageShift = PageShift - PteShift;
const Addr NPtePage = ULL(1) << NPtePageShift;
const Addr PteMask = NPtePage - 1;
// User Virtual
const Addr USegBase = ULL(0x0);
const Addr USegEnd = ULL(0x000003ffffffffff);
// Kernel Direct Mapped
const Addr K0SegBase = ULL(0xfffffc0000000000);
const Addr K0SegEnd = ULL(0xfffffdffffffffff);
// Kernel Virtual
const Addr K1SegBase = ULL(0xfffffe0000000000);
const Addr K1SegEnd = ULL(0xffffffffffffffff);
// For loading... XXX This maybe could be USegEnd?? --ali
const Addr LoadAddrMask = ULL(0xffffffffff);
////////////////////////////////////////////////////////////////////////
//
// Interrupt levels
//
enum InterruptLevels
{
INTLEVEL_SOFTWARE_MIN = 4,
INTLEVEL_SOFTWARE_MAX = 19,
INTLEVEL_EXTERNAL_MIN = 20,
INTLEVEL_EXTERNAL_MAX = 34,
INTLEVEL_IRQ0 = 20,
INTLEVEL_IRQ1 = 21,
INTINDEX_ETHERNET = 0,
INTINDEX_SCSI = 1,
INTLEVEL_IRQ2 = 22,
INTLEVEL_IRQ3 = 23,
INTLEVEL_SERIAL = 33,
NumInterruptLevels = INTLEVEL_EXTERNAL_MAX
};
// EV5 modes
enum mode_type
{
mode_kernel = 0, // kernel
mode_executive = 1, // executive (unused by unix)
mode_supervisor = 2, // supervisor (unused by unix)
mode_user = 3, // user mode
mode_number // number of modes
};
// Constants Related to the number of registers
const int NumIntArchRegs = 32;
const int NumPALShadowRegs = 8;
const int NumFloatArchRegs = 32;
// @todo: Figure out what this number really should be.
const int NumMiscArchRegs = 77;
const int NumIntRegs = NumIntArchRegs + NumPALShadowRegs;
const int NumFloatRegs = NumFloatArchRegs;
const int NumMiscRegs = NumMiscArchRegs;
const int TotalNumRegs =
NumIntRegs + NumFloatRegs + NumMiscRegs + NumInternalProcRegs;
const int TotalDataRegs = NumIntRegs + NumFloatRegs;
// semantically meaningful register indices
const int ZeroReg = 31; // architecturally meaningful
// the rest of these depend on the ABI
const int StackPointerReg = 30;
const int GlobalPointerReg = 29;
const int ProcedureValueReg = 27;
const int ReturnAddressReg = 26;
const int ReturnValueReg = 0;
const int FramePointerReg = 15;
const int SyscallNumReg = 0;
const int FirstArgumentReg = 16;
const int SyscallPseudoReturnReg = 20;
const int LogVMPageSize = 13; // 8K bytes
const int VMPageSize = (1 << LogVMPageSize);
const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned
const int MachineBytes = 8;
const int WordBytes = 4;
const int HalfwordBytes = 2;
const int ByteBytes = 1;
// return a no-op instruction... used for instruction fetch faults
// Alpha UNOP (ldq_u r31,0(r0))
const ExtMachInst NoopMachInst = 0x2ffe0000;
} // namespace AlphaISA
#endif // __ARCH_ALPHA_ISA_TRAITS_HH__ #endif // __ARCH_ALPHA_ISA_TRAITS_HH__

View file

@ -152,7 +152,7 @@ Statistics::changeMode(cpu_mode newmode, ThreadContext *tc)
void void
Statistics::mode(cpu_mode newmode, ThreadContext *tc) Statistics::mode(cpu_mode newmode, ThreadContext *tc)
{ {
Addr pcbb = tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp23); Addr pcbb = tc->readMiscRegNoEffect(IPR_PALtemp23);
if (newmode == kernel && pcbb == idleProcess) if (newmode == kernel && pcbb == idleProcess)
newmode = idle; newmode = idle;
@ -213,5 +213,5 @@ Statistics::unserialize(Checkpoint *cp, const string &section)
themode = (cpu_mode)exemode; themode = (cpu_mode)exemode;
} }
} /* end namespace AlphaISA::Kernel */ } // namespace Kernel
} /* end namespace AlphaISA */ } // namespace AlphaISA

View file

@ -62,15 +62,15 @@ class Statistics : public ::Kernel::Statistics
void changeMode(cpu_mode newmode, ThreadContext *tc); void changeMode(cpu_mode newmode, ThreadContext *tc);
private: private:
Stats::Vector<> _callpal; Stats::Vector _callpal;
// Stats::Vector<> _faults; // Stats::Vector _faults;
Stats::Vector<> _mode; Stats::Vector _mode;
Stats::Vector<> _modeGood; Stats::Vector _modeGood;
Stats::Formula _modeFraction; Stats::Formula _modeFraction;
Stats::Vector<> _modeTicks; Stats::Vector _modeTicks;
Stats::Scalar<> _swap_context; Stats::Scalar _swap_context;
public: public:
Statistics(System *system); Statistics(System *system);
@ -90,7 +90,7 @@ class Statistics : public ::Kernel::Statistics
void unserialize(Checkpoint *cp, const std::string &section); void unserialize(Checkpoint *cp, const std::string &section);
}; };
} /* end namespace AlphaISA::Kernel */ } // namespace Kernel
} /* end namespace AlphaISA */ } // namespace AlphaISA
#endif // __ARCH_ALPHA_KERNEL_STATS_HH__ #endif // __ARCH_ALPHA_KERNEL_STATS_HH__

View file

@ -28,47 +28,44 @@
* Authors: Korey Sewell * Authors: Korey Sewell
*/ */
#include "arch/alpha/linux/linux.hh"
#include <fcntl.h> #include <fcntl.h>
#include "arch/alpha/linux/linux.hh"
// open(2) flags translation table // open(2) flags translation table
OpenFlagTransTable AlphaLinux::openFlagTable[] = { OpenFlagTransTable AlphaLinux::openFlagTable[] = {
#ifdef _MSC_VER #ifdef _MSC_VER
{ AlphaLinux::TGT_O_RDONLY, _O_RDONLY }, { AlphaLinux::TGT_O_RDONLY, _O_RDONLY },
{ AlphaLinux::TGT_O_WRONLY, _O_WRONLY }, { AlphaLinux::TGT_O_WRONLY, _O_WRONLY },
{ AlphaLinux::TGT_O_RDWR, _O_RDWR }, { AlphaLinux::TGT_O_RDWR, _O_RDWR },
{ AlphaLinux::TGT_O_APPEND, _O_APPEND }, { AlphaLinux::TGT_O_APPEND, _O_APPEND },
{ AlphaLinux::TGT_O_CREAT, _O_CREAT }, { AlphaLinux::TGT_O_CREAT, _O_CREAT },
{ AlphaLinux::TGT_O_TRUNC, _O_TRUNC }, { AlphaLinux::TGT_O_TRUNC, _O_TRUNC },
{ AlphaLinux::TGT_O_EXCL, _O_EXCL }, { AlphaLinux::TGT_O_EXCL, _O_EXCL },
#ifdef _O_NONBLOCK #ifdef _O_NONBLOCK
{ AlphaLinux::TGT_O_NONBLOCK, _O_NONBLOCK }, { AlphaLinux::TGT_O_NONBLOCK, _O_NONBLOCK },
#endif #endif
#ifdef _O_NOCTTY #ifdef _O_NOCTTY
{ AlphaLinux::TGT_O_NOCTTY, _O_NOCTTY }, { AlphaLinux::TGT_O_NOCTTY, _O_NOCTTY },
#endif #endif
#ifdef _O_SYNC #ifdef _O_SYNC
{ AlphaLinux::TGT_O_SYNC, _O_SYNC }, { AlphaLinux::TGT_O_SYNC, _O_SYNC },
#endif #endif
#else /* !_MSC_VER */ #else /* !_MSC_VER */
{ AlphaLinux::TGT_O_RDONLY, O_RDONLY }, { AlphaLinux::TGT_O_RDONLY, O_RDONLY },
{ AlphaLinux::TGT_O_WRONLY, O_WRONLY }, { AlphaLinux::TGT_O_WRONLY, O_WRONLY },
{ AlphaLinux::TGT_O_RDWR, O_RDWR }, { AlphaLinux::TGT_O_RDWR, O_RDWR },
{ AlphaLinux::TGT_O_APPEND, O_APPEND }, { AlphaLinux::TGT_O_APPEND, O_APPEND },
{ AlphaLinux::TGT_O_CREAT, O_CREAT }, { AlphaLinux::TGT_O_CREAT, O_CREAT },
{ AlphaLinux::TGT_O_TRUNC, O_TRUNC }, { AlphaLinux::TGT_O_TRUNC, O_TRUNC },
{ AlphaLinux::TGT_O_EXCL, O_EXCL }, { AlphaLinux::TGT_O_EXCL, O_EXCL },
{ AlphaLinux::TGT_O_NONBLOCK, O_NONBLOCK }, { AlphaLinux::TGT_O_NONBLOCK, O_NONBLOCK },
{ AlphaLinux::TGT_O_NOCTTY, O_NOCTTY }, { AlphaLinux::TGT_O_NOCTTY, O_NOCTTY },
#ifdef O_SYNC #ifdef O_SYNC
{ AlphaLinux::TGT_O_SYNC, O_SYNC }, { AlphaLinux::TGT_O_SYNC, O_SYNC },
#endif #endif
#endif /* _MSC_VER */ #endif /* _MSC_VER */
}; };
const int AlphaLinux::NUM_OPEN_FLAGS = const int AlphaLinux::NUM_OPEN_FLAGS =
(sizeof(AlphaLinux::openFlagTable)/sizeof(AlphaLinux::openFlagTable[0])); (sizeof(AlphaLinux::openFlagTable)/sizeof(AlphaLinux::openFlagTable[0]));

View file

@ -28,8 +28,8 @@
* Authors: Korey Sewell * Authors: Korey Sewell
*/ */
#ifndef __ALPHA_ALPHA_LINUX_HH #ifndef __ALPHA_ALPHA_LINUX_LINUX_HH__
#define __ALPHA_ALPHA_LINUX_HH #define __ALPHA_ALPHA_LINUX_LINUX_HH__
#include "kern/linux/linux.hh" #include "kern/linux/linux.hh"
@ -50,21 +50,21 @@ class AlphaLinux : public Linux
//@{ //@{
/// open(2) flag values. /// open(2) flag values.
static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY
static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY
static const int TGT_O_RDWR = 00000002; //!< O_RDWR static const int TGT_O_RDWR = 00000002; //!< O_RDWR
static const int TGT_O_NONBLOCK = 00000004; //!< O_NONBLOCK static const int TGT_O_NONBLOCK = 00000004; //!< O_NONBLOCK
static const int TGT_O_APPEND = 00000010; //!< O_APPEND static const int TGT_O_APPEND = 00000010; //!< O_APPEND
static const int TGT_O_CREAT = 00001000; //!< O_CREAT static const int TGT_O_CREAT = 00001000; //!< O_CREAT
static const int TGT_O_TRUNC = 00002000; //!< O_TRUNC static const int TGT_O_TRUNC = 00002000; //!< O_TRUNC
static const int TGT_O_EXCL = 00004000; //!< O_EXCL static const int TGT_O_EXCL = 00004000; //!< O_EXCL
static const int TGT_O_NOCTTY = 00010000; //!< O_NOCTTY static const int TGT_O_NOCTTY = 00010000; //!< O_NOCTTY
static const int TGT_O_SYNC = 00040000; //!< O_SYNC static const int TGT_O_SYNC = 00040000; //!< O_SYNC
static const int TGT_O_DRD = 00100000; //!< O_DRD static const int TGT_O_DRD = 00100000; //!< O_DRD
static const int TGT_O_DIRECTIO = 00200000; //!< O_DIRECTIO static const int TGT_O_DIRECTIO = 00200000; //!< O_DIRECTIO
static const int TGT_O_CACHE = 00400000; //!< O_CACHE static const int TGT_O_CACHE = 00400000; //!< O_CACHE
static const int TGT_O_DSYNC = 02000000; //!< O_DSYNC static const int TGT_O_DSYNC = 02000000; //!< O_DSYNC
static const int TGT_O_RSYNC = 04000000; //!< O_RSYNC static const int TGT_O_RSYNC = 04000000; //!< O_RSYNC
//@} //@}
/// For mmap(). /// For mmap().
@ -72,13 +72,13 @@ class AlphaLinux : public Linux
//@{ //@{
/// For getsysinfo(). /// For getsysinfo().
static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string
static const unsigned GSI_CPU_INFO = 59; //!< CPU information static const unsigned GSI_CPU_INFO = 59; //!< CPU information
static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type
static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine static const unsigned GSI_MAX_CPU = 30; //!< max # CPUs on machine
static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system
static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB
static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz
static const unsigned GSI_IEEE_FP_CONTROL = 45; static const unsigned GSI_IEEE_FP_CONTROL = 45;
//@} //@}
@ -127,4 +127,4 @@ class AlphaLinux : public Linux
}; };
}; };
#endif #endif // __ALPHA_ALPHA_LINUX_LINUX_HH__

View file

@ -43,18 +43,16 @@
using namespace std; using namespace std;
using namespace AlphaISA; using namespace AlphaISA;
/// Target uname() handler. /// Target uname() handler.
static SyscallReturn static SyscallReturn
unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc) ThreadContext *tc)
{ {
TypedBufferArg<Linux::utsname> name(tc->getSyscallArg(0)); TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, 0));
strcpy(name->sysname, "Linux"); strcpy(name->sysname, "Linux");
strcpy(name->nodename, "m5.eecs.umich.edu"); strcpy(name->nodename, "m5.eecs.umich.edu");
strcpy(name->release, "2.4.20"); strcpy(name->release, "2.6.26");
strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003");
strcpy(name->machine, "alpha"); strcpy(name->machine, "alpha");
@ -69,13 +67,13 @@ static SyscallReturn
osf_getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, osf_getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc) ThreadContext *tc)
{ {
unsigned op = tc->getSyscallArg(0); unsigned op = process->getSyscallArg(tc, 0);
// unsigned nbytes = tc->getSyscallArg(2); // unsigned nbytes = process->getSyscallArg(tc, 2);
switch (op) { switch (op) {
case 45: { // GSI_IEEE_FP_CONTROL case 45: { // GSI_IEEE_FP_CONTROL
TypedBufferArg<uint64_t> fpcr(tc->getSyscallArg(1)); TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1));
// I don't think this exactly matches the HW FPCR // I don't think this exactly matches the HW FPCR
*fpcr = 0; *fpcr = 0;
fpcr.copyOut(tc->getMemPort()); fpcr.copyOut(tc->getMemPort());
@ -96,13 +94,13 @@ static SyscallReturn
osf_setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, osf_setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc) ThreadContext *tc)
{ {
unsigned op = tc->getSyscallArg(0); unsigned op = process->getSyscallArg(tc, 0);
// unsigned nbytes = tc->getSyscallArg(2); // unsigned nbytes = process->getSyscallArg(tc, 2);
switch (op) { switch (op) {
case 14: { // SSI_IEEE_FP_CONTROL case 14: { // SSI_IEEE_FP_CONTROL
TypedBufferArg<uint64_t> fpcr(tc->getSyscallArg(1)); TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1));
// I don't think this exactly matches the HW FPCR // I don't think this exactly matches the HW FPCR
fpcr.copyIn(tc->getMemPort()); fpcr.copyIn(tc->getMemPort());
DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): " DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): "
@ -138,7 +136,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 14 */ SyscallDesc("mknod", unimplementedFunc), /* 14 */ SyscallDesc("mknod", unimplementedFunc),
/* 15 */ SyscallDesc("chmod", chmodFunc<AlphaLinux>), /* 15 */ SyscallDesc("chmod", chmodFunc<AlphaLinux>),
/* 16 */ SyscallDesc("chown", chownFunc), /* 16 */ SyscallDesc("chown", chownFunc),
/* 17 */ SyscallDesc("brk", obreakFunc), /* 17 */ SyscallDesc("brk", brkFunc),
/* 18 */ SyscallDesc("osf_getfsstat", unimplementedFunc), /* 18 */ SyscallDesc("osf_getfsstat", unimplementedFunc),
/* 19 */ SyscallDesc("lseek", lseekFunc), /* 19 */ SyscallDesc("lseek", lseekFunc),
/* 20 */ SyscallDesc("getxpid", getpidPseudoFunc), /* 20 */ SyscallDesc("getxpid", getpidPseudoFunc),
@ -179,9 +177,9 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 55 */ SyscallDesc("osf_reboot", unimplementedFunc), /* 55 */ SyscallDesc("osf_reboot", unimplementedFunc),
/* 56 */ SyscallDesc("osf_revoke", unimplementedFunc), /* 56 */ SyscallDesc("osf_revoke", unimplementedFunc),
/* 57 */ SyscallDesc("symlink", unimplementedFunc), /* 57 */ SyscallDesc("symlink", unimplementedFunc),
/* 58 */ SyscallDesc("readlink", unimplementedFunc), /* 58 */ SyscallDesc("readlink", readlinkFunc),
/* 59 */ SyscallDesc("execve", unimplementedFunc), /* 59 */ SyscallDesc("execve", unimplementedFunc),
/* 60 */ SyscallDesc("umask", unimplementedFunc), /* 60 */ SyscallDesc("umask", umaskFunc),
/* 61 */ SyscallDesc("chroot", unimplementedFunc), /* 61 */ SyscallDesc("chroot", unimplementedFunc),
/* 62 */ SyscallDesc("osf_old_fstat", unimplementedFunc), /* 62 */ SyscallDesc("osf_old_fstat", unimplementedFunc),
/* 63 */ SyscallDesc("getpgrp", unimplementedFunc), /* 63 */ SyscallDesc("getpgrp", unimplementedFunc),
@ -250,14 +248,14 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 126 */ SyscallDesc("setreuid", unimplementedFunc), /* 126 */ SyscallDesc("setreuid", unimplementedFunc),
/* 127 */ SyscallDesc("setregid", unimplementedFunc), /* 127 */ SyscallDesc("setregid", unimplementedFunc),
/* 128 */ SyscallDesc("rename", renameFunc), /* 128 */ SyscallDesc("rename", renameFunc),
/* 129 */ SyscallDesc("truncate", unimplementedFunc), /* 129 */ SyscallDesc("truncate", truncateFunc),
/* 130 */ SyscallDesc("ftruncate", unimplementedFunc), /* 130 */ SyscallDesc("ftruncate", ftruncateFunc),
/* 131 */ SyscallDesc("flock", unimplementedFunc), /* 131 */ SyscallDesc("flock", unimplementedFunc),
/* 132 */ SyscallDesc("setgid", unimplementedFunc), /* 132 */ SyscallDesc("setgid", unimplementedFunc),
/* 133 */ SyscallDesc("sendto", unimplementedFunc), /* 133 */ SyscallDesc("sendto", unimplementedFunc),
/* 134 */ SyscallDesc("shutdown", unimplementedFunc), /* 134 */ SyscallDesc("shutdown", unimplementedFunc),
/* 135 */ SyscallDesc("socketpair", unimplementedFunc), /* 135 */ SyscallDesc("socketpair", unimplementedFunc),
/* 136 */ SyscallDesc("mkdir", unimplementedFunc), /* 136 */ SyscallDesc("mkdir", mkdirFunc),
/* 137 */ SyscallDesc("rmdir", unimplementedFunc), /* 137 */ SyscallDesc("rmdir", unimplementedFunc),
/* 138 */ SyscallDesc("osf_utimes", unimplementedFunc), /* 138 */ SyscallDesc("osf_utimes", unimplementedFunc),
/* 139 */ SyscallDesc("osf_old_sigreturn", unimplementedFunc), /* 139 */ SyscallDesc("osf_old_sigreturn", unimplementedFunc),
@ -465,7 +463,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 338 */ SyscallDesc("afs_syscall", unimplementedFunc), /* 338 */ SyscallDesc("afs_syscall", unimplementedFunc),
/* 339 */ SyscallDesc("uname", unameFunc), /* 339 */ SyscallDesc("uname", unameFunc),
/* 340 */ SyscallDesc("nanosleep", unimplementedFunc), /* 340 */ SyscallDesc("nanosleep", unimplementedFunc),
/* 341 */ SyscallDesc("mremap", unimplementedFunc), /* 341 */ SyscallDesc("mremap", mremapFunc<AlphaLinux>),
/* 342 */ SyscallDesc("nfsservctl", unimplementedFunc), /* 342 */ SyscallDesc("nfsservctl", unimplementedFunc),
/* 343 */ SyscallDesc("setresuid", unimplementedFunc), /* 343 */ SyscallDesc("setresuid", unimplementedFunc),
/* 344 */ SyscallDesc("getresuid", unimplementedFunc), /* 344 */ SyscallDesc("getresuid", unimplementedFunc),
@ -491,7 +489,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 364 */ SyscallDesc("getrusage", getrusageFunc<AlphaLinux>), /* 364 */ SyscallDesc("getrusage", getrusageFunc<AlphaLinux>),
/* 365 */ SyscallDesc("wait4", unimplementedFunc), /* 365 */ SyscallDesc("wait4", unimplementedFunc),
/* 366 */ SyscallDesc("adjtimex", unimplementedFunc), /* 366 */ SyscallDesc("adjtimex", unimplementedFunc),
/* 367 */ SyscallDesc("getcwd", unimplementedFunc), /* 367 */ SyscallDesc("getcwd", getcwdFunc),
/* 368 */ SyscallDesc("capget", unimplementedFunc), /* 368 */ SyscallDesc("capget", unimplementedFunc),
/* 369 */ SyscallDesc("capset", unimplementedFunc), /* 369 */ SyscallDesc("capset", unimplementedFunc),
/* 370 */ SyscallDesc("sendfile", unimplementedFunc), /* 370 */ SyscallDesc("sendfile", unimplementedFunc),
@ -581,7 +579,7 @@ AlphaLinuxProcess::AlphaLinuxProcess(LiveProcessParams * params,
SyscallDesc* SyscallDesc*
AlphaLinuxProcess::getDesc(int callnum) AlphaLinuxProcess::getDesc(int callnum)
{ {
if (callnum < 0 || callnum > Num_Syscall_Descs) if (callnum < 0 || callnum >= Num_Syscall_Descs)
return NULL; return NULL;
return &syscallDescs[callnum]; return &syscallDescs[callnum];
} }

View file

@ -51,4 +51,5 @@ class AlphaLinuxProcess : public AlphaLiveProcess
}; };
} // namespace AlphaISA } // namespace AlphaISA
#endif // __ALPHA_LINUX_PROCESS_HH__ #endif // __ALPHA_LINUX_PROCESS_HH__

View file

@ -157,7 +157,6 @@ LinuxAlphaSystem::~LinuxAlphaSystem()
delete printThreadEvent; delete printThreadEvent;
} }
void void
LinuxAlphaSystem::setDelayLoop(ThreadContext *tc) LinuxAlphaSystem::setDelayLoop(ThreadContext *tc)
{ {
@ -169,11 +168,9 @@ LinuxAlphaSystem::setDelayLoop(ThreadContext *tc)
vp = tc->getVirtPort(); vp = tc->getVirtPort();
vp->writeHtoG(addr, (uint32_t)((cpuFreq / intrFreq) * 0.9988)); vp->writeHtoG(addr, (uint32_t)((cpuFreq / intrFreq) * 0.9988));
tc->delVirtPort(vp);
} }
} }
void void
LinuxAlphaSystem::SkipDelayLoopEvent::process(ThreadContext *tc) LinuxAlphaSystem::SkipDelayLoopEvent::process(ThreadContext *tc)
{ {

View file

@ -43,9 +43,6 @@ class IdleStartEvent;
#include "kern/linux/events.hh" #include "kern/linux/events.hh"
#include "params/LinuxAlphaSystem.hh" #include "params/LinuxAlphaSystem.hh"
using namespace AlphaISA;
using namespace Linux;
/** /**
* This class contains linux specific system code (Loading, Events). * This class contains linux specific system code (Loading, Events).
* It points to objects that are the system binaries to load and patches them * It points to objects that are the system binaries to load and patches them
@ -54,23 +51,20 @@ using namespace Linux;
class LinuxAlphaSystem : public AlphaSystem class LinuxAlphaSystem : public AlphaSystem
{ {
private: private:
class SkipDelayLoopEvent : public SkipFuncEvent struct SkipDelayLoopEvent : public SkipFuncEvent
{ {
public:
SkipDelayLoopEvent(PCEventQueue *q, const std::string &desc, Addr addr) SkipDelayLoopEvent(PCEventQueue *q, const std::string &desc, Addr addr)
: SkipFuncEvent(q, desc, addr) {} : SkipFuncEvent(q, desc, addr) {}
virtual void process(ThreadContext *tc); virtual void process(ThreadContext *tc);
}; };
class PrintThreadInfo : public PCEvent struct PrintThreadInfo : public PCEvent
{ {
public:
PrintThreadInfo(PCEventQueue *q, const std::string &desc, Addr addr) PrintThreadInfo(PCEventQueue *q, const std::string &desc, Addr addr)
: PCEvent(q, desc, addr) {} : PCEvent(q, desc, addr) {}
virtual void process(ThreadContext *tc); virtual void process(ThreadContext *tc);
}; };
/** /**
* Addresses defining where the kernel bootloader places various * Addresses defining where the kernel bootloader places various
* elements. Details found in include/asm-alpha/system.h * elements. Details found in include/asm-alpha/system.h
@ -112,7 +106,7 @@ class LinuxAlphaSystem : public AlphaSystem
* PC based event to skip the dprink() call and emulate its * PC based event to skip the dprink() call and emulate its
* functionality * functionality
*/ */
DebugPrintkEvent *debugPrintkEvent; Linux::DebugPrintkEvent *debugPrintkEvent;
/** /**
* Skip calculate_delay_loop() rather than waiting for this to be * Skip calculate_delay_loop() rather than waiting for this to be

View file

@ -55,7 +55,7 @@ class ThreadInfo
CopyOut(tc, &data, addr, sizeof(T)); CopyOut(tc, &data, addr, sizeof(T));
data = TheISA::gtoh(data); data = AlphaISA::gtoh(data);
return true; return true;
} }
@ -76,7 +76,7 @@ class ThreadInfo
Addr sp; Addr sp;
if (!addr) if (!addr)
addr = tc->readMiscRegNoEffect(TheISA::IPR_PALtemp23); addr = tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp23);
FunctionalPort *p = tc->getPhysPort(); FunctionalPort *p = tc->getPhysPort();
p->readBlob(addr, (uint8_t *)&sp, sizeof(Addr)); p->readBlob(addr, (uint8_t *)&sp, sizeof(Addr));
@ -147,6 +147,6 @@ class ThreadInfo
} }
}; };
/* namespace Linux */ } } // namespace Linux
#endif // __ARCH_ALPHA_LINUX_LINUX_THREADINFO_HH__ #endif // __ARCH_ALPHA_LINUX_LINUX_THREADINFO_HH__

View file

@ -49,9 +49,8 @@
#include "base/misc.hh" #include "base/misc.hh"
#include "mem/request.hh" #include "mem/request.hh"
namespace AlphaISA {
namespace AlphaISA
{
template <class XC> template <class XC>
inline void inline void
handleLockedRead(XC *xc, Request *req) handleLockedRead(XC *xc, Request *req)
@ -86,9 +85,9 @@ handleLockedWrite(XC *xc, Request *req)
stCondFailures++; stCondFailures++;
xc->setStCondFailures(stCondFailures); xc->setStCondFailures(stCondFailures);
if (stCondFailures % 100000 == 0) { if (stCondFailures % 100000 == 0) {
warn("cpu %d: %d consecutive " warn("context %d: %d consecutive "
"store conditional failures\n", "store conditional failures\n",
xc->readCpuId(), stCondFailures); xc->contextId(), stCondFailures);
} }
// store conditional failed already, so don't issue it to mem // store conditional failed already, so don't issue it to mem
@ -99,7 +98,6 @@ handleLockedWrite(XC *xc, Request *req)
return true; return true;
} }
} // namespace AlphaISA } // namespace AlphaISA
#endif #endif // __ARCH_ALPHA_LOCKED_MEM_HH__

View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2008 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_ALPHA_MICROCODE_ROM_HH__
#define __ARCH_ALPHA_MICROCODE_ROM_HH__
#include "sim/microcode_rom.hh"
namespace AlphaISA
{
using ::MicrocodeRom;
}
#endif // __ARCH_ALPHA_MICROCODE_ROM_HH__

View file

@ -30,121 +30,121 @@
* Kevin Lim * Kevin Lim
*/ */
#include <cassert>
#include "arch/alpha/miscregfile.hh" #include "arch/alpha/miscregfile.hh"
#include "base/misc.hh" #include "base/misc.hh"
namespace AlphaISA namespace AlphaISA {
void
MiscRegFile::serialize(std::ostream &os)
{ {
SERIALIZE_SCALAR(fpcr);
void SERIALIZE_SCALAR(uniq);
MiscRegFile::serialize(std::ostream &os) SERIALIZE_SCALAR(lock_flag);
{ SERIALIZE_SCALAR(lock_addr);
SERIALIZE_SCALAR(fpcr); SERIALIZE_ARRAY(ipr, NumInternalProcRegs);
SERIALIZE_SCALAR(uniq);
SERIALIZE_SCALAR(lock_flag);
SERIALIZE_SCALAR(lock_addr);
SERIALIZE_ARRAY(ipr, NumInternalProcRegs);
}
void
MiscRegFile::unserialize(Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_SCALAR(fpcr);
UNSERIALIZE_SCALAR(uniq);
UNSERIALIZE_SCALAR(lock_flag);
UNSERIALIZE_SCALAR(lock_addr);
UNSERIALIZE_ARRAY(ipr, NumInternalProcRegs);
}
MiscReg
MiscRegFile::readRegNoEffect(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;
default:
assert(misc_reg < NumInternalProcRegs);
return ipr[misc_reg];
}
}
MiscReg
MiscRegFile::readReg(int misc_reg, ThreadContext *tc)
{
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;
default:
return readIpr(misc_reg, tc);
}
}
void
MiscRegFile::setRegNoEffect(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;
default:
assert(misc_reg < NumInternalProcRegs);
ipr[misc_reg] = val;
return;
}
}
void
MiscRegFile::setReg(int misc_reg, const MiscReg &val,
ThreadContext *tc)
{
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:
setIpr(misc_reg, val, tc);
return;
}
}
} }
void
MiscRegFile::unserialize(Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_SCALAR(fpcr);
UNSERIALIZE_SCALAR(uniq);
UNSERIALIZE_SCALAR(lock_flag);
UNSERIALIZE_SCALAR(lock_addr);
UNSERIALIZE_ARRAY(ipr, NumInternalProcRegs);
}
MiscReg
MiscRegFile::readRegNoEffect(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;
default:
assert(misc_reg < NumInternalProcRegs);
return ipr[misc_reg];
}
}
MiscReg
MiscRegFile::readReg(int misc_reg, ThreadContext *tc)
{
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;
default:
return readIpr(misc_reg, tc);
}
}
void
MiscRegFile::setRegNoEffect(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;
default:
assert(misc_reg < NumInternalProcRegs);
ipr[misc_reg] = val;
return;
}
}
void
MiscRegFile::setReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
{
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:
setIpr(misc_reg, val, tc);
return;
}
}
} // namespace AlphaISA

View file

@ -32,85 +32,79 @@
#ifndef __ARCH_ALPHA_MISCREGFILE_HH__ #ifndef __ARCH_ALPHA_MISCREGFILE_HH__
#define __ARCH_ALPHA_MISCREGFILE_HH__ #define __ARCH_ALPHA_MISCREGFILE_HH__
#include <iosfwd>
#include "arch/alpha/ipr.hh" #include "arch/alpha/ipr.hh"
#include "arch/alpha/types.hh" #include "arch/alpha/types.hh"
#include "sim/host.hh" #include "sim/host.hh"
#include "sim/serialize.hh" #include "sim/serialize.hh"
#include <iostream>
class Checkpoint; class Checkpoint;
class ThreadContext; class ThreadContext;
namespace AlphaISA namespace AlphaISA {
{
enum MiscRegIndex
{
MISCREG_FPCR = NumInternalProcRegs,
MISCREG_UNIQ,
MISCREG_LOCKFLAG,
MISCREG_LOCKADDR,
MISCREG_INTR
};
static inline std::string getMiscRegName(RegIndex) enum MiscRegIndex
{
MISCREG_FPCR = NumInternalProcRegs,
MISCREG_UNIQ,
MISCREG_LOCKFLAG,
MISCREG_LOCKADDR,
MISCREG_INTR
};
class MiscRegFile
{
public:
friend class RegFile;
typedef uint64_t InternalProcReg;
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;
InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs
protected:
InternalProcReg readIpr(int idx, ThreadContext *tc);
void setIpr(int idx, InternalProcReg val, ThreadContext *tc);
public:
MiscRegFile()
{ {
return ""; initializeIprTable();
} }
class MiscRegFile { // These functions should be removed once the simplescalar cpu
protected: // model has been replaced.
uint64_t fpcr; // floating point condition codes int getInstAsid();
uint64_t uniq; // process-unique register int getDataAsid();
bool lock_flag; // lock flag for LL/SC
Addr lock_addr; // lock address for LL/SC
int intr_flag;
public: MiscReg readRegNoEffect(int misc_reg);
MiscRegFile() MiscReg readReg(int misc_reg, ThreadContext *tc);
{
initializeIprTable();
}
MiscReg readRegNoEffect(int misc_reg); void setRegNoEffect(int misc_reg, const MiscReg &val);
void setReg(int misc_reg, const MiscReg &val, ThreadContext *tc);
MiscReg readReg(int misc_reg, ThreadContext *tc); void
clear()
{
fpcr = 0;
uniq = 0;
lock_flag = 0;
lock_addr = 0;
intr_flag = 0;
}
//These functions should be removed once the simplescalar cpu model void serialize(std::ostream &os);
//has been replaced. void unserialize(Checkpoint *cp, const std::string &section);
int getInstAsid(); };
int getDataAsid();
void setRegNoEffect(int misc_reg, const MiscReg &val); void copyIprs(ThreadContext *src, ThreadContext *dest);
void setReg(int misc_reg, const MiscReg &val, } // namespace AlphaISA
ThreadContext *tc);
void clear() #endif // __ARCH_ALPHA_MISCREGFILE_HH__
{
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);
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);
friend class RegFile;
};
void copyIprs(ThreadContext *src, ThreadContext *dest);
}
#endif

View file

@ -39,9 +39,8 @@
#include "mem/packet.hh" #include "mem/packet.hh"
namespace AlphaISA {
namespace AlphaISA
{
inline Tick inline Tick
handleIprRead(ThreadContext *xc, Packet *pkt) handleIprRead(ThreadContext *xc, Packet *pkt)
{ {
@ -58,4 +57,4 @@ handleIprWrite(ThreadContext *xc, Packet *pkt)
} // namespace AlphaISA } // namespace AlphaISA
#endif #endif // __ARCH_ALPHA_MMAPED_IPR_HH__

View file

@ -30,275 +30,273 @@
#include "arch/alpha/osfpal.hh" #include "arch/alpha/osfpal.hh"
namespace {
const char *strings[PAL::NumCodes] = {
// Priviledged PAL instructions
"halt", // 0x00
"cflush", // 0x01
"draina", // 0x02
0, // 0x03
0, // 0x04
0, // 0x05
0, // 0x06
0, // 0x07
0, // 0x08
"cserve", // 0x09
"swppal", // 0x0a
0, // 0x0b
0, // 0x0c
"wripir", // 0x0d
0, // 0x0e
0, // 0x0f
"rdmces", // 0x10
"wrmces", // 0x11
0, // 0x12
0, // 0x13
0, // 0x14
0, // 0x15
0, // 0x16
0, // 0x17
0, // 0x18
0, // 0x19
0, // 0x1a
0, // 0x1b
0, // 0x1c
0, // 0x1d
0, // 0x1e
0, // 0x1f
0, // 0x20
0, // 0x21
0, // 0x22
0, // 0x23
0, // 0x24
0, // 0x25
0, // 0x26
0, // 0x27
0, // 0x28
0, // 0x29
0, // 0x2a
"wrfen", // 0x2b
0, // 0x2c
"wrvptptr", // 0x2d
0, // 0x2e
0, // 0x2f
"swpctx", // 0x30
"wrval", // 0x31
"rdval", // 0x32
"tbi", // 0x33
"wrent", // 0x34
"swpipl", // 0x35
"rdps", // 0x36
"wrkgp", // 0x37
"wrusp", // 0x38
"wrperfmon", // 0x39
"rdusp", // 0x3a
0, // 0x3b
"whami", // 0x3c
"retsys", // 0x3d
"wtint", // 0x3e
"rti", // 0x3f
0, // 0x40
0, // 0x41
0, // 0x42
0, // 0x43
0, // 0x44
0, // 0x45
0, // 0x46
0, // 0x47
0, // 0x48
0, // 0x49
0, // 0x4a
0, // 0x4b
0, // 0x4c
0, // 0x4d
0, // 0x4e
0, // 0x4f
0, // 0x50
0, // 0x51
0, // 0x52
0, // 0x53
0, // 0x54
0, // 0x55
0, // 0x56
0, // 0x57
0, // 0x58
0, // 0x59
0, // 0x5a
0, // 0x5b
0, // 0x5c
0, // 0x5d
0, // 0x5e
0, // 0x5f
0, // 0x60
0, // 0x61
0, // 0x62
0, // 0x63
0, // 0x64
0, // 0x65
0, // 0x66
0, // 0x67
0, // 0x68
0, // 0x69
0, // 0x6a
0, // 0x6b
0, // 0x6c
0, // 0x6d
0, // 0x6e
0, // 0x6f
0, // 0x70
0, // 0x71
0, // 0x72
0, // 0x73
0, // 0x74
0, // 0x75
0, // 0x76
0, // 0x77
0, // 0x78
0, // 0x79
0, // 0x7a
0, // 0x7b
0, // 0x7c
0, // 0x7d
0, // 0x7e
0, // 0x7f
// Unpriviledged PAL instructions
"bpt", // 0x80
"bugchk", // 0x81
0, // 0x82
"callsys", // 0x83
0, // 0x84
0, // 0x85
"imb", // 0x86
0, // 0x87
0, // 0x88
0, // 0x89
0, // 0x8a
0, // 0x8b
0, // 0x8c
0, // 0x8d
0, // 0x8e
0, // 0x8f
0, // 0x90
0, // 0x91
"urti", // 0x92
0, // 0x93
0, // 0x94
0, // 0x95
0, // 0x96
0, // 0x97
0, // 0x98
0, // 0x99
0, // 0x9a
0, // 0x9b
0, // 0x9c
0, // 0x9d
"rdunique", // 0x9e
"wrunique", // 0x9f
0, // 0xa0
0, // 0xa1
0, // 0xa2
0, // 0xa3
0, // 0xa4
0, // 0xa5
0, // 0xa6
0, // 0xa7
0, // 0xa8
0, // 0xa9
"gentrap", // 0xaa
0, // 0xab
0, // 0xac
0, // 0xad
"clrfen", // 0xae
0, // 0xaf
0, // 0xb0
0, // 0xb1
0, // 0xb2
0, // 0xb3
0, // 0xb4
0, // 0xb5
0, // 0xb6
0, // 0xb7
0, // 0xb8
0, // 0xb9
0, // 0xba
0, // 0xbb
0, // 0xbc
0, // 0xbd
"nphalt", // 0xbe
"copypal", // 0xbf
#if 0
0, // 0xc0
0, // 0xc1
0, // 0xc2
0, // 0xc3
0, // 0xc4
0, // 0xc5
0, // 0xc6
0, // 0xc7
0, // 0xc8
0, // 0xc9
0, // 0xca
0, // 0xcb
0, // 0xcc
0, // 0xcd
0, // 0xce
0, // 0xcf
0, // 0xd0
0, // 0xd1
0, // 0xd2
0, // 0xd3
0, // 0xd4
0, // 0xd5
0, // 0xd6
0, // 0xd7
0, // 0xd8
0, // 0xd9
0, // 0xda
0, // 0xdb
0, // 0xdc
0, // 0xdd
0, // 0xde
0, // 0xdf
0, // 0xe0
0, // 0xe1
0, // 0xe2
0, // 0xe3
0, // 0xe4
0, // 0xe5
0, // 0xe6
0, // 0xe7
0, // 0xe8
0, // 0xe9
0, // 0xea
0, // 0xeb
0, // 0xec
0, // 0xed
0, // 0xee
0, // 0xef
0, // 0xf0
0, // 0xf1
0, // 0xf2
0, // 0xf3
0, // 0xf4
0, // 0xf5
0, // 0xf6
0, // 0xf7
0, // 0xf8
0, // 0xf9
0, // 0xfa
0, // 0xfb
0, // 0xfc
0, // 0xfd
0, // 0xfe
0 // 0xff
#endif
};
}
const char * const char *
PAL::name(int index) PAL::name(int index)
{ {
static const char *strings[PAL::NumCodes] = {
// Priviledged PAL instructions
"halt", // 0x00
"cflush", // 0x01
"draina", // 0x02
0, // 0x03
0, // 0x04
0, // 0x05
0, // 0x06
0, // 0x07
0, // 0x08
"cserve", // 0x09
"swppal", // 0x0a
0, // 0x0b
0, // 0x0c
"wripir", // 0x0d
0, // 0x0e
0, // 0x0f
"rdmces", // 0x10
"wrmces", // 0x11
0, // 0x12
0, // 0x13
0, // 0x14
0, // 0x15
0, // 0x16
0, // 0x17
0, // 0x18
0, // 0x19
0, // 0x1a
0, // 0x1b
0, // 0x1c
0, // 0x1d
0, // 0x1e
0, // 0x1f
0, // 0x20
0, // 0x21
0, // 0x22
0, // 0x23
0, // 0x24
0, // 0x25
0, // 0x26
0, // 0x27
0, // 0x28
0, // 0x29
0, // 0x2a
"wrfen", // 0x2b
0, // 0x2c
"wrvptptr", // 0x2d
0, // 0x2e
0, // 0x2f
"swpctx", // 0x30
"wrval", // 0x31
"rdval", // 0x32
"tbi", // 0x33
"wrent", // 0x34
"swpipl", // 0x35
"rdps", // 0x36
"wrkgp", // 0x37
"wrusp", // 0x38
"wrperfmon", // 0x39
"rdusp", // 0x3a
0, // 0x3b
"whami", // 0x3c
"retsys", // 0x3d
"wtint", // 0x3e
"rti", // 0x3f
0, // 0x40
0, // 0x41
0, // 0x42
0, // 0x43
0, // 0x44
0, // 0x45
0, // 0x46
0, // 0x47
0, // 0x48
0, // 0x49
0, // 0x4a
0, // 0x4b
0, // 0x4c
0, // 0x4d
0, // 0x4e
0, // 0x4f
0, // 0x50
0, // 0x51
0, // 0x52
0, // 0x53
0, // 0x54
0, // 0x55
0, // 0x56
0, // 0x57
0, // 0x58
0, // 0x59
0, // 0x5a
0, // 0x5b
0, // 0x5c
0, // 0x5d
0, // 0x5e
0, // 0x5f
0, // 0x60
0, // 0x61
0, // 0x62
0, // 0x63
0, // 0x64
0, // 0x65
0, // 0x66
0, // 0x67
0, // 0x68
0, // 0x69
0, // 0x6a
0, // 0x6b
0, // 0x6c
0, // 0x6d
0, // 0x6e
0, // 0x6f
0, // 0x70
0, // 0x71
0, // 0x72
0, // 0x73
0, // 0x74
0, // 0x75
0, // 0x76
0, // 0x77
0, // 0x78
0, // 0x79
0, // 0x7a
0, // 0x7b
0, // 0x7c
0, // 0x7d
0, // 0x7e
0, // 0x7f
// Unpriviledged PAL instructions
"bpt", // 0x80
"bugchk", // 0x81
0, // 0x82
"callsys", // 0x83
0, // 0x84
0, // 0x85
"imb", // 0x86
0, // 0x87
0, // 0x88
0, // 0x89
0, // 0x8a
0, // 0x8b
0, // 0x8c
0, // 0x8d
0, // 0x8e
0, // 0x8f
0, // 0x90
0, // 0x91
"urti", // 0x92
0, // 0x93
0, // 0x94
0, // 0x95
0, // 0x96
0, // 0x97
0, // 0x98
0, // 0x99
0, // 0x9a
0, // 0x9b
0, // 0x9c
0, // 0x9d
"rdunique", // 0x9e
"wrunique", // 0x9f
0, // 0xa0
0, // 0xa1
0, // 0xa2
0, // 0xa3
0, // 0xa4
0, // 0xa5
0, // 0xa6
0, // 0xa7
0, // 0xa8
0, // 0xa9
"gentrap", // 0xaa
0, // 0xab
0, // 0xac
0, // 0xad
"clrfen", // 0xae
0, // 0xaf
0, // 0xb0
0, // 0xb1
0, // 0xb2
0, // 0xb3
0, // 0xb4
0, // 0xb5
0, // 0xb6
0, // 0xb7
0, // 0xb8
0, // 0xb9
0, // 0xba
0, // 0xbb
0, // 0xbc
0, // 0xbd
"nphalt", // 0xbe
"copypal", // 0xbf
#if 0
0, // 0xc0
0, // 0xc1
0, // 0xc2
0, // 0xc3
0, // 0xc4
0, // 0xc5
0, // 0xc6
0, // 0xc7
0, // 0xc8
0, // 0xc9
0, // 0xca
0, // 0xcb
0, // 0xcc
0, // 0xcd
0, // 0xce
0, // 0xcf
0, // 0xd0
0, // 0xd1
0, // 0xd2
0, // 0xd3
0, // 0xd4
0, // 0xd5
0, // 0xd6
0, // 0xd7
0, // 0xd8
0, // 0xd9
0, // 0xda
0, // 0xdb
0, // 0xdc
0, // 0xdd
0, // 0xde
0, // 0xdf
0, // 0xe0
0, // 0xe1
0, // 0xe2
0, // 0xe3
0, // 0xe4
0, // 0xe5
0, // 0xe6
0, // 0xe7
0, // 0xe8
0, // 0xe9
0, // 0xea
0, // 0xeb
0, // 0xec
0, // 0xed
0, // 0xee
0, // 0xef
0, // 0xf0
0, // 0xf1
0, // 0xf2
0, // 0xf3
0, // 0xf4
0, // 0xf5
0, // 0xf6
0, // 0xf7
0, // 0xf8
0, // 0xf9
0, // 0xfa
0, // 0xfb
0, // 0xfc
0, // 0xfd
0, // 0xfe
0 // 0xff
#endif
};
if (index > NumCodes || index < 0) if (index > NumCodes || index < 0)
return 0; return 0;

View file

@ -28,8 +28,8 @@
* Authors: Nathan Binkert * Authors: Nathan Binkert
*/ */
#ifndef __OSFPAL_HH__ #ifndef __ARCH_ALPHA_OSFPAL_HH__
#define __OSFPAL_HH__ #define __ARCH_ALPHA_OSFPAL_HH__
struct PAL struct PAL
{ {
@ -79,4 +79,4 @@ struct PAL
static const char *name(int index); static const char *name(int index);
}; };
#endif // __OSFPAL_HH__ #endif // __ARCH_ALPHA_OSFPAL_HH__

View file

@ -31,33 +31,34 @@
#include "arch/alpha/pagetable.hh" #include "arch/alpha/pagetable.hh"
#include "sim/serialize.hh" #include "sim/serialize.hh"
namespace AlphaISA namespace AlphaISA {
{
void
TlbEntry::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 void
TlbEntry::unserialize(Checkpoint *cp, const std::string &section) TlbEntry::serialize(std::ostream &os)
{ {
UNSERIALIZE_SCALAR(tag); SERIALIZE_SCALAR(tag);
UNSERIALIZE_SCALAR(ppn); SERIALIZE_SCALAR(ppn);
UNSERIALIZE_SCALAR(xre); SERIALIZE_SCALAR(xre);
UNSERIALIZE_SCALAR(xwe); SERIALIZE_SCALAR(xwe);
UNSERIALIZE_SCALAR(asn); SERIALIZE_SCALAR(asn);
UNSERIALIZE_SCALAR(asma); SERIALIZE_SCALAR(asma);
UNSERIALIZE_SCALAR(fonr); SERIALIZE_SCALAR(fonr);
UNSERIALIZE_SCALAR(fonw); SERIALIZE_SCALAR(fonw);
UNSERIALIZE_SCALAR(valid); SERIALIZE_SCALAR(valid);
}
} }
void
TlbEntry::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);
}
} //namespace AlphaISA

View file

@ -38,97 +38,109 @@
namespace AlphaISA { namespace AlphaISA {
struct VAddr struct VAddr
{ {
static const int ImplBits = 43; static const int ImplBits = 43;
static const Addr ImplMask = (ULL(1) << ImplBits) - 1; static const Addr ImplMask = (ULL(1) << ImplBits) - 1;
static const Addr UnImplMask = ~ImplMask; static const Addr UnImplMask = ~ImplMask;
VAddr(Addr a) : addr(a) {} Addr addr;
Addr addr;
operator Addr() const { return addr; }
const VAddr &operator=(Addr a) { addr = a; return *this; }
Addr vpn() const { return (addr & ImplMask) >> PageShift; } VAddr(Addr a) : addr(a) {}
Addr page() const { return addr & PageMask; } operator Addr() const { return addr; }
Addr offset() const { return addr & PageOffset; } const VAddr &operator=(Addr a) { addr = a; return *this; }
Addr level3() const Addr vpn() const { return (addr & ImplMask) >> PageShift; }
{ return AlphaISA::PteAddr(addr >> PageShift); } Addr page() const { return addr & PageMask; }
Addr level2() const Addr offset() const { return addr & PageOffset; }
{ return AlphaISA::PteAddr(addr >> NPtePageShift + PageShift); }
Addr level1() const
{ return AlphaISA::PteAddr(addr >> 2 * NPtePageShift + PageShift); }
};
struct PageTableEntry
{
PageTableEntry(uint64_t e) : entry(e) {}
uint64_t entry;
operator uint64_t() const { return entry; }
const PageTableEntry &operator=(uint64_t e) { entry = e; return *this; }
const PageTableEntry &operator=(const PageTableEntry &e)
{ entry = e.entry; return *this; }
Addr _pfn() const { return (entry >> 32) & 0xffffffff; }
Addr _sw() const { return (entry >> 16) & 0xffff; }
int _rsv0() const { return (entry >> 14) & 0x3; }
bool _uwe() const { return (entry >> 13) & 0x1; }
bool _kwe() const { return (entry >> 12) & 0x1; }
int _rsv1() const { return (entry >> 10) & 0x3; }
bool _ure() const { return (entry >> 9) & 0x1; }
bool _kre() const { return (entry >> 8) & 0x1; }
bool _nomb() const { return (entry >> 7) & 0x1; }
int _gh() const { return (entry >> 5) & 0x3; }
bool _asm_() const { return (entry >> 4) & 0x1; }
bool _foe() const { return (entry >> 3) & 0x1; }
bool _fow() const { return (entry >> 2) & 0x1; }
bool _for() const { return (entry >> 1) & 0x1; }
bool valid() const { return (entry >> 0) & 0x1; }
Addr paddr() const { return _pfn() << PageShift; }
};
// ITB/DTB table entry
struct TlbEntry
{
//Construct an entry that maps to physical address addr.
TlbEntry(Addr _asn, Addr _vaddr, Addr _paddr)
{
VAddr vaddr(_vaddr);
VAddr paddr(_paddr);
tag = vaddr.vpn();
ppn = paddr.vpn();
xre = 15;
xwe = 15;
asn = _asn;
asma = false;
fonr = false;
fonw = false;
valid = true;
}
TlbEntry()
{}
Addr tag; // virtual page number tag
Addr ppn; // physical page number
uint8_t xre; // read permissions - VMEM_PERM_* mask
uint8_t xwe; // write permissions - VMEM_PERM_* mask
uint8_t asn; // address space number
bool asma; // address space match
bool fonr; // fault on read
bool fonw; // fault on write
bool valid; // valid page table entry
Addr pageStart()
{
return ppn << PageShift;
}
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
};
Addr level3() const
{ return PteAddr(addr >> PageShift); }
Addr level2() const
{ return PteAddr(addr >> (NPtePageShift + PageShift)); }
Addr level1() const
{ return PteAddr(addr >> (2 * NPtePageShift + PageShift)); }
}; };
struct PageTableEntry
{
PageTableEntry(uint64_t e) : entry(e) {}
uint64_t entry;
operator uint64_t() const { return entry; }
const PageTableEntry &operator=(uint64_t e) { entry = e; return *this; }
const PageTableEntry &operator=(const PageTableEntry &e)
{ entry = e.entry; return *this; }
Addr _pfn() const { return (entry >> 32) & 0xffffffff; }
Addr _sw() const { return (entry >> 16) & 0xffff; }
int _rsv0() const { return (entry >> 14) & 0x3; }
bool _uwe() const { return (entry >> 13) & 0x1; }
bool _kwe() const { return (entry >> 12) & 0x1; }
int _rsv1() const { return (entry >> 10) & 0x3; }
bool _ure() const { return (entry >> 9) & 0x1; }
bool _kre() const { return (entry >> 8) & 0x1; }
bool _nomb() const { return (entry >> 7) & 0x1; }
int _gh() const { return (entry >> 5) & 0x3; }
bool _asm_() const { return (entry >> 4) & 0x1; }
bool _foe() const { return (entry >> 3) & 0x1; }
bool _fow() const { return (entry >> 2) & 0x1; }
bool _for() const { return (entry >> 1) & 0x1; }
bool valid() const { return (entry >> 0) & 0x1; }
Addr paddr() const { return _pfn() << PageShift; }
};
// ITB/DTB table entry
struct TlbEntry
{
Addr tag; // virtual page number tag
Addr ppn; // physical page number
uint8_t xre; // read permissions - VMEM_PERM_* mask
uint8_t xwe; // write permissions - VMEM_PERM_* mask
uint8_t asn; // address space number
bool asma; // address space match
bool fonr; // fault on read
bool fonw; // fault on write
bool valid; // valid page table entry
//Construct an entry that maps to physical address addr.
TlbEntry(Addr _asn, Addr _vaddr, Addr _paddr)
{
VAddr vaddr(_vaddr);
VAddr paddr(_paddr);
tag = vaddr.vpn();
ppn = paddr.vpn();
xre = 15;
xwe = 15;
asn = _asn;
asma = false;
fonr = false;
fonw = false;
valid = true;
}
TlbEntry()
{}
void
updateVaddr(Addr new_vaddr)
{
VAddr vaddr(new_vaddr);
tag = vaddr.vpn();
}
Addr
pageStart()
{
return ppn << PageShift;
}
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
};
} // namespace AlphaISA
#endif // __ARCH_ALPHA_PAGETABLE_H__ #endif // __ARCH_ALPHA_PAGETABLE_H__

View file

@ -38,62 +38,72 @@
class ThreadContext; class ThreadContext;
namespace AlphaISA namespace AlphaISA {
class Predecoder
{ {
class Predecoder protected:
ThreadContext *tc;
// The extended machine instruction being generated
ExtMachInst ext_inst;
public:
Predecoder(ThreadContext * _tc)
: tc(_tc)
{}
ThreadContext *
getTC()
{ {
protected: return tc;
ThreadContext * tc; }
//The extended machine instruction being generated
ExtMachInst ext_inst;
public: void
Predecoder(ThreadContext * _tc) : tc(_tc) setTC(ThreadContext * _tc)
{} {
tc = _tc;
}
ThreadContext * getTC() void
{ process()
return tc; { }
}
void setTC(ThreadContext * _tc) void
{ reset()
tc = _tc; { }
}
void process() // Use this to give data to the predecoder. This should be used
{ // when there is control flow.
} void
moreBytes(Addr pc, Addr fetchPC, MachInst inst)
void reset() {
{} ext_inst = inst;
//Use this to give data to the predecoder. This should be used
//when there is control flow.
void moreBytes(Addr pc, Addr fetchPC, MachInst inst)
{
ext_inst = inst;
#if FULL_SYSTEM #if FULL_SYSTEM
ext_inst|=(static_cast<ExtMachInst>(pc & 0x1) << 32); ext_inst |= (static_cast<ExtMachInst>(pc & 0x1) << 32);
#endif #endif
} }
bool needMoreBytes() bool
{ needMoreBytes()
return true; {
} return true;
}
bool extMachInstReady() bool
{ extMachInstReady()
return true; {
} return true;
}
//This returns a constant reference to the ExtMachInst to avoid a copy // This returns a constant reference to the ExtMachInst to avoid a copy
const ExtMachInst & getExtMachInst() const ExtMachInst &
{ getExtMachInst()
return ext_inst; {
} return ext_inst;
}; }
}; };
} // namespace AlphaISA
#endif // __ARCH_ALPHA_PREDECODER_HH__ #endif // __ARCH_ALPHA_PREDECODER_HH__

View file

@ -32,16 +32,20 @@
#include "arch/alpha/isa_traits.hh" #include "arch/alpha/isa_traits.hh"
#include "arch/alpha/process.hh" #include "arch/alpha/process.hh"
#include "base/loader/object_file.hh" #include "base/loader/object_file.hh"
#include "base/loader/elf_object.hh"
#include "base/misc.hh" #include "base/misc.hh"
#include "cpu/thread_context.hh" #include "cpu/thread_context.hh"
#include "mem/page_table.hh"
#include "sim/process_impl.hh"
#include "sim/system.hh" #include "sim/system.hh"
using namespace AlphaISA; using namespace AlphaISA;
using namespace std; using namespace std;
AlphaLiveProcess::AlphaLiveProcess(LiveProcessParams * params, static const int SyscallSuccessReg = 19;
ObjectFile *objFile)
AlphaLiveProcess::AlphaLiveProcess(LiveProcessParams *params,
ObjectFile *objFile)
: LiveProcess(params, objFile) : LiveProcess(params, objFile)
{ {
brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize(); brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();
@ -58,6 +62,117 @@ AlphaLiveProcess::AlphaLiveProcess(LiveProcessParams * params,
// Set pointer for next thread stack. Reserve 8M for main stack. // Set pointer for next thread stack. Reserve 8M for main stack.
next_thread_stack_base = stack_base - (8 * 1024 * 1024); next_thread_stack_base = stack_base - (8 * 1024 * 1024);
}
void
AlphaLiveProcess::argsInit(int intSize, int pageSize)
{
objFile->loadSections(initVirtMem);
typedef AuxVector<uint64_t> auxv_t;
std::vector<auxv_t> auxv;
ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile);
if(elfObject)
{
// modern glibc uses a bunch of auxiliary vectors to set up
// TLS as well as do a bunch of other stuff
// these vectors go on the bottom of the stack, below argc/argv/envp
// pointers but above actual arg strings
// I don't have all the ones glibc looks at here, but so far it doesn't
// seem to be a problem.
// check out _dl_aux_init() in glibc/elf/dl-support.c for details
// --Lisa
auxv.push_back(auxv_t(M5_AT_PAGESZ, AlphaISA::VMPageSize));
auxv.push_back(auxv_t(M5_AT_CLKTCK, 100));
auxv.push_back(auxv_t(M5_AT_PHDR, elfObject->programHeaderTable()));
DPRINTF(Loader, "auxv at PHDR %08p\n", elfObject->programHeaderTable());
auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount()));
auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint()));
auxv.push_back(auxv_t(M5_AT_UID, uid()));
auxv.push_back(auxv_t(M5_AT_EUID, euid()));
auxv.push_back(auxv_t(M5_AT_GID, gid()));
auxv.push_back(auxv_t(M5_AT_EGID, egid()));
}
// Calculate how much space we need for arg & env & auxv arrays.
int argv_array_size = intSize * (argv.size() + 1);
int envp_array_size = intSize * (envp.size() + 1);
int auxv_array_size = intSize * 2 * (auxv.size() + 1);
int arg_data_size = 0;
for (int i = 0; i < argv.size(); ++i) {
arg_data_size += argv[i].size() + 1;
}
int env_data_size = 0;
for (int i = 0; i < envp.size(); ++i) {
env_data_size += envp[i].size() + 1;
}
int space_needed =
argv_array_size +
envp_array_size +
auxv_array_size +
arg_data_size +
env_data_size;
if (space_needed < 32*1024)
space_needed = 32*1024;
// set bottom of stack
stack_min = stack_base - space_needed;
// align it
stack_min = roundDown(stack_min, pageSize);
stack_size = stack_base - stack_min;
// map memory
pTable->allocate(stack_min, roundUp(stack_size, pageSize));
// map out initial stack contents
Addr argv_array_base = stack_min + intSize; // room for argc
Addr envp_array_base = argv_array_base + argv_array_size;
Addr auxv_array_base = envp_array_base + envp_array_size;
Addr arg_data_base = auxv_array_base + auxv_array_size;
Addr env_data_base = arg_data_base + arg_data_size;
// write contents to stack
uint64_t argc = argv.size();
if (intSize == 8)
argc = htog((uint64_t)argc);
else if (intSize == 4)
argc = htog((uint32_t)argc);
else
panic("Unknown int size");
initVirtMem->writeBlob(stack_min, (uint8_t*)&argc, intSize);
copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);
copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
//Copy the aux stuff
for(int x = 0; x < auxv.size(); x++)
{
initVirtMem->writeBlob(auxv_array_base + x * 2 * intSize,
(uint8_t*)&(auxv[x].a_type), intSize);
initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize,
(uint8_t*)&(auxv[x].a_val), intSize);
}
ThreadContext *tc = system->getThreadContext(contextIds[0]);
setSyscallArg(tc, 0, argc);
setSyscallArg(tc, 1, argv_array_base);
tc->setIntReg(StackPointerReg, stack_min);
Addr prog_entry = objFile->entryPoint();
tc->setPC(prog_entry);
tc->setNextPC(prog_entry + sizeof(MachInst));
#if THE_ISA != ALPHA_ISA //e.g. MIPS or Sparc
tc->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
#endif
} }
void void
@ -66,15 +181,49 @@ AlphaLiveProcess::startup()
if (checkpointRestored) if (checkpointRestored)
return; return;
Process::startup();
argsInit(MachineBytes, VMPageSize); argsInit(MachineBytes, VMPageSize);
threadContexts[0]->setIntReg(GlobalPointerReg, objFile->globalPointer()); ThreadContext *tc = system->getThreadContext(contextIds[0]);
//Opperate in user mode tc->setIntReg(GlobalPointerReg, objFile->globalPointer());
threadContexts[0]->setMiscRegNoEffect(IPR_ICM, 0x18); //Operate in user mode
tc->setMiscRegNoEffect(IPR_ICM, 0x18);
//No super page mapping //No super page mapping
threadContexts[0]->setMiscRegNoEffect(IPR_MCSR, 0); tc->setMiscRegNoEffect(IPR_MCSR, 0);
//Set this to 0 for now, but it should be unique for each process //Set this to 0 for now, but it should be unique for each process
threadContexts[0]->setMiscRegNoEffect(IPR_DTB_ASN, M5_pid << 57); tc->setMiscRegNoEffect(IPR_DTB_ASN, M5_pid << 57);
} }
AlphaISA::IntReg
AlphaLiveProcess::getSyscallArg(ThreadContext *tc, int i)
{
assert(i < 6);
return tc->readIntReg(FirstArgumentReg + i);
}
void
AlphaLiveProcess::setSyscallArg(ThreadContext *tc,
int i, AlphaISA::IntReg val)
{
assert(i < 6);
tc->setIntReg(FirstArgumentReg + i, val);
}
void
AlphaLiveProcess::setSyscallReturn(ThreadContext *tc,
SyscallReturn return_value)
{
// check for error condition. Alpha syscall convention is to
// indicate success/failure in reg a3 (r19) and put the
// return value itself in the standard return value reg (v0).
if (return_value.successful()) {
// no error
tc->setIntReg(SyscallSuccessReg, 0);
tc->setIntReg(ReturnValueReg, return_value.value());
} else {
// got an error, return details
tc->setIntReg(SyscallSuccessReg, (IntReg)-1);
tc->setIntReg(ReturnValueReg, -return_value.value());
}
}

View file

@ -29,24 +29,24 @@
* Ali Saidi * Ali Saidi
*/ */
#ifndef __ALPHA_PROCESS_HH__ #ifndef __ARCH_ALPHA_PROCESS_HH__
#define __ALPHA_PROCESS_HH__ #define __ARCH_ALPHA_PROCESS_HH__
#include <string>
#include <vector>
#include "sim/process.hh" #include "sim/process.hh"
class ObjectFile;
class System;
class AlphaLiveProcess : public LiveProcess class AlphaLiveProcess : public LiveProcess
{ {
protected: protected:
AlphaLiveProcess(LiveProcessParams * params, ObjectFile *objFile); AlphaLiveProcess(LiveProcessParams *params, ObjectFile *objFile);
void startup(); void startup();
void argsInit(int intSize, int pageSize);
public:
AlphaISA::IntReg getSyscallArg(ThreadContext *tc, int i);
void setSyscallArg(ThreadContext *tc, int i, AlphaISA::IntReg val);
void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value);
}; };
#endif // __ARCH_ALPHA_PROCESS_HH__
#endif // __ALPHA_PROCESS_HH__

View file

@ -33,67 +33,68 @@
#include "arch/alpha/regfile.hh" #include "arch/alpha/regfile.hh"
#include "cpu/thread_context.hh" #include "cpu/thread_context.hh"
namespace AlphaISA using namespace std;
namespace AlphaISA {
void
RegFile::serialize(EventManager *em, ostream &os)
{ {
void intRegFile.serialize(os);
RegFile::serialize(std::ostream &os) floatRegFile.serialize(os);
{ miscRegFile.serialize(os);
intRegFile.serialize(os); SERIALIZE_SCALAR(pc);
floatRegFile.serialize(os); SERIALIZE_SCALAR(npc);
miscRegFile.serialize(os);
SERIALIZE_SCALAR(pc);
SERIALIZE_SCALAR(npc);
#if FULL_SYSTEM #if FULL_SYSTEM
SERIALIZE_SCALAR(intrflag); SERIALIZE_SCALAR(intrflag);
#endif #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->setMiscRegNoEffect(AlphaISA::MISCREG_FPCR,
src->readMiscRegNoEffect(AlphaISA::MISCREG_FPCR));
dest->setMiscRegNoEffect(AlphaISA::MISCREG_UNIQ,
src->readMiscRegNoEffect(AlphaISA::MISCREG_UNIQ));
dest->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG,
src->readMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG));
dest->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKADDR,
src->readMiscRegNoEffect(AlphaISA::MISCREG_LOCKADDR));
copyIprs(src, dest);
}
} }
void
RegFile::unserialize(EventManager *em, Checkpoint *cp, const 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 < 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->setMiscRegNoEffect(MISCREG_FPCR,
src->readMiscRegNoEffect(MISCREG_FPCR));
dest->setMiscRegNoEffect(MISCREG_UNIQ,
src->readMiscRegNoEffect(MISCREG_UNIQ));
dest->setMiscRegNoEffect(MISCREG_LOCKFLAG,
src->readMiscRegNoEffect(MISCREG_LOCKFLAG));
dest->setMiscRegNoEffect(MISCREG_LOCKADDR,
src->readMiscRegNoEffect(MISCREG_LOCKADDR));
copyIprs(src, dest);
}
} // namespace AlphaISA

View file

@ -43,163 +43,187 @@
//XXX These should be implemented by someone who knows the alpha stuff better //XXX These should be implemented by someone who knows the alpha stuff better
class Checkpoint; class Checkpoint;
class EventManager;
class ThreadContext; class ThreadContext;
namespace AlphaISA namespace AlphaISA {
{
class RegFile { class RegFile {
protected:
Addr pc; // program counter
Addr npc; // next-cycle program counter
Addr nnpc; // next next-cycle program counter
protected: public:
Addr pc; // program counter Addr
Addr npc; // next-cycle program counter readPC()
Addr nnpc; {
return pc;
}
public: void
Addr readPC() setPC(Addr val)
{ {
return pc; pc = val;
} }
void setPC(Addr val) Addr
{ readNextPC()
pc = val; {
} return npc;
}
Addr readNextPC() void
{ setNextPC(Addr val)
return npc; {
} npc = val;
}
void setNextPC(Addr val) Addr
{ readNextNPC()
npc = val; {
} return npc + sizeof(MachInst);
}
Addr readNextNPC() void
{ setNextNPC(Addr val)
return npc + sizeof(MachInst); { }
}
void setNextNPC(Addr val) protected:
{ } IntRegFile intRegFile; // (signed) integer register file
FloatRegFile floatRegFile; // floating point register file
protected: MiscRegFile miscRegFile; // control register file
IntRegFile intRegFile; // (signed) integer register file
FloatRegFile floatRegFile; // floating point register file
MiscRegFile miscRegFile; // control register file
public:
public:
#if FULL_SYSTEM #if FULL_SYSTEM
int intrflag; // interrupt flag int intrflag; // interrupt flag
inline int instAsid()
{ return miscRegFile.getInstAsid(); } int
inline int dataAsid() instAsid()
{ return miscRegFile.getDataAsid(); } {
return miscRegFile.getInstAsid();
}
int
dataAsid()
{
return miscRegFile.getDataAsid();
}
#endif // FULL_SYSTEM #endif // FULL_SYSTEM
void clear() void
{ clear()
intRegFile.clear();
floatRegFile.clear();
miscRegFile.clear();
}
MiscReg readMiscRegNoEffect(int miscReg)
{
return miscRegFile.readRegNoEffect(miscReg);
}
MiscReg readMiscReg(int miscReg, ThreadContext *tc)
{
return miscRegFile.readReg(miscReg, tc);
}
void setMiscRegNoEffect(int miscReg, const MiscReg &val)
{
miscRegFile.setRegNoEffect(miscReg, val);
}
void setMiscReg(int miscReg, const MiscReg &val,
ThreadContext * tc)
{
miscRegFile.setReg(miscReg, val, tc);
}
FloatReg readFloatReg(int floatReg)
{
return floatRegFile.d[floatReg];
}
FloatReg readFloatReg(int floatReg, int width)
{
return readFloatReg(floatReg);
}
FloatRegBits readFloatRegBits(int floatReg)
{
return floatRegFile.q[floatReg];
}
FloatRegBits readFloatRegBits(int floatReg, int width)
{
return readFloatRegBits(floatReg);
}
void setFloatReg(int floatReg, const FloatReg &val)
{
floatRegFile.d[floatReg] = val;
}
void setFloatReg(int floatReg, const FloatReg &val, int width)
{
setFloatReg(floatReg, val);
}
void setFloatRegBits(int floatReg, const FloatRegBits &val)
{
floatRegFile.q[floatReg] = val;
}
void setFloatRegBits(int floatReg, const FloatRegBits &val, int width)
{
setFloatRegBits(floatReg, val);
}
IntReg readIntReg(int intReg)
{
return intRegFile.readReg(intReg);
}
void setIntReg(int intReg, const IntReg &val)
{
intRegFile.setReg(intReg, val);
}
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
void changeContext(RegContextParam param, RegContextVal val)
{
//This would be an alternative place to call/implement
//the swapPALShadow function
}
};
static inline int flattenIntIndex(ThreadContext * tc, int reg)
{ {
return reg; intRegFile.clear();
floatRegFile.clear();
miscRegFile.clear();
} }
static inline int flattenFloatIndex(ThreadContext * tc, int reg) MiscReg
readMiscRegNoEffect(int miscReg)
{ {
return reg; return miscRegFile.readRegNoEffect(miscReg);
} }
void copyRegs(ThreadContext *src, ThreadContext *dest); MiscReg
readMiscReg(int miscReg, ThreadContext *tc)
{
return miscRegFile.readReg(miscReg, tc);
}
void
setMiscRegNoEffect(int miscReg, const MiscReg &val)
{
miscRegFile.setRegNoEffect(miscReg, val);
}
void
setMiscReg(int miscReg, const MiscReg &val, ThreadContext *tc)
{
miscRegFile.setReg(miscReg, val, tc);
}
FloatReg
readFloatReg(int floatReg)
{
return floatRegFile.d[floatReg];
}
FloatReg
readFloatReg(int floatReg, int width)
{
return readFloatReg(floatReg);
}
FloatRegBits
readFloatRegBits(int floatReg)
{
return floatRegFile.q[floatReg];
}
FloatRegBits
readFloatRegBits(int floatReg, int width)
{
return readFloatRegBits(floatReg);
}
void
setFloatReg(int floatReg, const FloatReg &val)
{
floatRegFile.d[floatReg] = val;
}
void
setFloatReg(int floatReg, const FloatReg &val, int width)
{
setFloatReg(floatReg, val);
}
void
setFloatRegBits(int floatReg, const FloatRegBits &val)
{
floatRegFile.q[floatReg] = val;
}
void
setFloatRegBits(int floatReg, const FloatRegBits &val, int width)
{
setFloatRegBits(floatReg, val);
}
IntReg
readIntReg(int intReg)
{
return intRegFile.readReg(intReg);
}
void
setIntReg(int intReg, const IntReg &val)
{
intRegFile.setReg(intReg, val);
}
void serialize(EventManager *em, std::ostream &os);
void unserialize(EventManager *em, Checkpoint *cp,
const std::string &section);
};
static inline int
flattenIntIndex(ThreadContext * tc, int reg)
{
return reg;
}
static inline int
flattenFloatIndex(ThreadContext * tc, int reg)
{
return reg;
}
void copyRegs(ThreadContext *src, ThreadContext *dest);
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
} // namespace AlphaISA } // namespace AlphaISA
#endif #endif // __ARCH_ALPHA_REGFILE_HH__

View file

@ -30,7 +30,7 @@
/* /*
* Copyright (c) 1990, 1993 * Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This software was developed by the Computer Systems Engineering group * This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
@ -38,8 +38,8 @@
* *
* All advertising materials mentioning features or use of this software * All advertising materials mentioning features or use of this software
* must display the following acknowledgement: * must display the following acknowledgement:
* This product includes software developed by the University of * This product includes software developed by the University of
* California, Lawrence Berkeley Laboratories. * California, Lawrence Berkeley Laboratories.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -51,8 +51,8 @@
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement: * must display the following acknowledgement:
* This product includes software developed by the University of * This product includes software developed by the University of
* California, Berkeley and its contributors. * California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -69,7 +69,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94 * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94
*/ */
/*- /*-
@ -89,8 +89,8 @@
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement: * must display the following acknowledgement:
* This product includes software developed by the NetBSD * This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors. * Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its * 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived * contributors may be used to endorse or promote products derived
* from this software without specific prior written permission. * from this software without specific prior written permission.
@ -117,9 +117,9 @@
*/ */
#include <sys/signal.h> #include <sys/signal.h>
#include <unistd.h>
#include <string> #include <string>
#include <unistd.h>
#include "config/full_system.hh" #include "config/full_system.hh"
#if FULL_SYSTEM #if FULL_SYSTEM
@ -140,19 +140,17 @@
#include "sim/system.hh" #include "sim/system.hh"
using namespace std; using namespace std;
using namespace TheISA; using namespace AlphaISA;
RemoteGDB::RemoteGDB(System *_system, ThreadContext *c) RemoteGDB::RemoteGDB(System *_system, ThreadContext *tc)
: BaseRemoteGDB(_system, c, KGDB_NUMREGS) : BaseRemoteGDB(_system, tc, KGDB_NUMREGS)
{ {
memset(gdbregs.regs, 0, gdbregs.bytes()); memset(gdbregs.regs, 0, gdbregs.bytes());
} }
/////////////////////////////////////////////////////////// /*
// RemoteGDB::acc * Determine if the mapping at va..(va+len) is valid.
// */
// Determine if the mapping at va..(va+len) is valid.
//
bool bool
RemoteGDB::acc(Addr va, size_t len) RemoteGDB::acc(Addr va, size_t len)
{ {
@ -161,12 +159,12 @@ RemoteGDB::acc(Addr va, size_t len)
#else #else
Addr last_va; Addr last_va;
va = TheISA::TruncPage(va); va = TruncPage(va);
last_va = TheISA::RoundPage(va + len); last_va = RoundPage(va + len);
do { do {
if (TheISA::IsK0Seg(va)) { if (IsK0Seg(va)) {
if (va < (TheISA::K0SegBase + pmem->size())) { if (va < (K0SegBase + pmem->size())) {
DPRINTF(GDBAcc, "acc: Mapping is valid K0SEG <= " DPRINTF(GDBAcc, "acc: Mapping is valid K0SEG <= "
"%#x < K0SEG + size\n", va); "%#x < K0SEG + size\n", va);
return true; return true;
@ -177,23 +175,25 @@ RemoteGDB::acc(Addr va, size_t len)
} }
} }
/** /**
* This code says that all accesses to palcode (instruction and data) * This code says that all accesses to palcode (instruction
* are valid since there isn't a va->pa mapping because palcode is * and data) are valid since there isn't a va->pa mapping
* accessed physically. At some point this should probably be cleaned up * because palcode is accessed physically. At some point this
* but there is no easy way to do it. * should probably be cleaned up but there is no easy way to
*/ * do it.
*/
if (AlphaISA::PcPAL(va) || va < 0x10000) if (PcPAL(va) || va < 0x10000)
return true; return true;
Addr ptbr = context->readMiscRegNoEffect(AlphaISA::IPR_PALtemp20); Addr ptbr = context->readMiscRegNoEffect(IPR_PALtemp20);
TheISA::PageTableEntry pte = TheISA::kernel_pte_lookup(context->getPhysPort(), ptbr, va); PageTableEntry pte =
kernel_pte_lookup(context->getPhysPort(), ptbr, va);
if (!pte.valid()) { if (!pte.valid()) {
DPRINTF(GDBAcc, "acc: %#x pte is invalid\n", va); DPRINTF(GDBAcc, "acc: %#x pte is invalid\n", va);
return false; return false;
} }
va += TheISA::PageBytes; va += PageBytes;
} while (va < last_va); } while (va < last_va);
DPRINTF(GDBAcc, "acc: %#x mapping is valid\n", va); DPRINTF(GDBAcc, "acc: %#x mapping is valid\n", va);
@ -201,11 +201,10 @@ RemoteGDB::acc(Addr va, size_t len)
#endif #endif
} }
/////////////////////////////////////////////////////////// /*
// RemoteGDB::getregs * Translate the kernel debugger register format into the GDB register
// * format.
// Translate the kernel debugger register format into */
// the GDB register format.
void void
RemoteGDB::getregs() RemoteGDB::getregs()
{ {
@ -214,45 +213,43 @@ RemoteGDB::getregs()
gdbregs.regs[KGDB_REG_PC] = context->readPC(); gdbregs.regs[KGDB_REG_PC] = context->readPC();
// @todo: Currently this is very Alpha specific. // @todo: Currently this is very Alpha specific.
if (AlphaISA::PcPAL(gdbregs.regs[KGDB_REG_PC])) { if (PcPAL(gdbregs.regs[KGDB_REG_PC])) {
for (int i = 0; i < TheISA::NumIntArchRegs; ++i) { for (int i = 0; i < NumIntArchRegs; ++i) {
gdbregs.regs[i] = context->readIntReg(AlphaISA::reg_redir[i]); gdbregs.regs[i] = context->readIntReg(reg_redir[i]);
} }
} else { } else {
for (int i = 0; i < TheISA::NumIntArchRegs; ++i) { for (int i = 0; i < NumIntArchRegs; ++i) {
gdbregs.regs[i] = context->readIntReg(i); gdbregs.regs[i] = context->readIntReg(i);
} }
} }
#ifdef KGDB_FP_REGS #ifdef KGDB_FP_REGS
for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) { for (int i = 0; i < NumFloatArchRegs; ++i) {
gdbregs.regs[i + KGDB_REG_F0] = context->readFloatRegBits(i); gdbregs.regs[i + KGDB_REG_F0] = context->readFloatRegBits(i);
} }
#endif #endif
} }
/////////////////////////////////////////////////////////// /*
// RemoteGDB::setregs * Translate the GDB register format into the kernel debugger register
// * format.
// Translate the GDB register format into the kernel */
// debugger register format.
//
void void
RemoteGDB::setregs() RemoteGDB::setregs()
{ {
// @todo: Currently this is very Alpha specific. // @todo: Currently this is very Alpha specific.
if (AlphaISA::PcPAL(gdbregs.regs[KGDB_REG_PC])) { if (PcPAL(gdbregs.regs[KGDB_REG_PC])) {
for (int i = 0; i < TheISA::NumIntArchRegs; ++i) { for (int i = 0; i < NumIntArchRegs; ++i) {
context->setIntReg(AlphaISA::reg_redir[i], gdbregs.regs[i]); context->setIntReg(reg_redir[i], gdbregs.regs[i]);
} }
} else { } else {
for (int i = 0; i < TheISA::NumIntArchRegs; ++i) { for (int i = 0; i < NumIntArchRegs; ++i) {
context->setIntReg(i, gdbregs.regs[i]); context->setIntReg(i, gdbregs.regs[i]);
} }
} }
#ifdef KGDB_FP_REGS #ifdef KGDB_FP_REGS
for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) { for (int i = 0; i < NumFloatArchRegs; ++i) {
context->setFloatRegBits(i, gdbregs.regs[i + KGDB_REG_F0]); context->setFloatRegBits(i, gdbregs.regs[i + KGDB_REG_F0]);
} }
#endif #endif

View file

@ -44,31 +44,29 @@ class System;
class ThreadContext; class ThreadContext;
class PhysicalMemory; class PhysicalMemory;
namespace AlphaISA namespace AlphaISA {
class RemoteGDB : public BaseRemoteGDB
{ {
class RemoteGDB : public BaseRemoteGDB protected:
{ Addr notTakenBkpt;
protected: Addr takenBkpt;
// Machine memory
bool write(Addr addr, size_t size, const char *data);
public: protected:
RemoteGDB(System *system, ThreadContext *context); void getregs();
void setregs();
bool acc(Addr addr, size_t len); void clearSingleStep();
void setSingleStep();
protected: // Machine memory
void getregs(); bool acc(Addr addr, size_t len);
void setregs(); bool write(Addr addr, size_t size, const char *data);
void clearSingleStep(); public:
void setSingleStep(); RemoteGDB(System *system, ThreadContext *context);
};
protected: } // namespace AlphaISA
Addr notTakenBkpt; #endif // __ARCH_ALPHA_REMOTE_GDB_HH__
Addr takenBkpt;
};
}
#endif /* __ARCH_ALPHA_REMOTE_GDB_H__ */

View file

@ -41,330 +41,326 @@
using namespace std; using namespace std;
namespace AlphaISA namespace AlphaISA {
ProcessInfo::ProcessInfo(ThreadContext *_tc)
: tc(_tc)
{ {
ProcessInfo::ProcessInfo(ThreadContext *_tc) Addr addr = 0;
: tc(_tc) VirtualPort *vp = tc->getVirtPort();
{ SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
Addr addr = 0;
VirtualPort *vp; if (!symtab->findAddress("thread_info_size", addr))
panic("thread info not compiled into kernel\n");
thread_info_size = vp->readGtoH<int32_t>(addr);
vp = tc->getVirtPort(); if (!symtab->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_size", addr)) if (!symtab->findAddress("thread_info_task", addr))
panic("thread info not compiled into kernel\n"); panic("thread info not compiled into kernel\n");
thread_info_size = vp->readGtoH<int32_t>(addr); task_off = vp->readGtoH<int32_t>(addr);
if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr)) if (!symtab->findAddress("task_struct_pid", addr))
panic("thread info not compiled into kernel\n"); panic("thread info not compiled into kernel\n");
task_struct_size = vp->readGtoH<int32_t>(addr); pid_off = vp->readGtoH<int32_t>(addr);
if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr)) if (!symtab->findAddress("task_struct_comm", addr))
panic("thread info not compiled into kernel\n"); panic("thread info not compiled into kernel\n");
task_off = vp->readGtoH<int32_t>(addr); name_off = vp->readGtoH<int32_t>(addr);
}
if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr)) Addr
panic("thread info not compiled into kernel\n"); ProcessInfo::task(Addr ksp) const
pid_off = vp->readGtoH<int32_t>(addr); {
Addr base = ksp & ~0x3fff;
if (base == ULL(0xfffffc0000000000))
return 0;
if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr)) Addr tsk;
panic("thread info not compiled into kernel\n");
name_off = vp->readGtoH<int32_t>(addr);
tc->delVirtPort(vp); VirtualPort *vp;
vp = tc->getVirtPort();
tsk = vp->readGtoH<Addr>(base + task_off);
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);
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;
System *sys = tc->getSystemPtr();
bool usermode =
(tc->readMiscRegNoEffect(IPR_DTB_CM) & 0x18) != 0;
Addr pc = tc->readNextPC();
bool kernel = sys->kernelStart <= pc && pc <= sys->kernelEnd;
if (usermode) {
stack.push_back(user);
return;
} }
Addr if (!kernel) {
ProcessInfo::task(Addr ksp) const stack.push_back(console);
{ return;
Addr base = ksp & ~0x3fff;
if (base == ULL(0xfffffc0000000000))
return 0;
Addr tsk;
VirtualPort *vp;
vp = tc->getVirtPort();
tsk = vp->readGtoH<Addr>(base + task_off);
tc->delVirtPort(vp);
return tsk;
} }
int SymbolTable *symtab = sys->kernelSymtab;
ProcessInfo::pid(Addr ksp) const Addr ksp = tc->readIntReg(StackPointerReg);
{ Addr bottom = ksp & ~0x3fff;
Addr task = this->task(ksp);
if (!task)
return -1;
uint16_t pd; if (is_call) {
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->readMiscRegNoEffect(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; Addr addr;
if (!symtab->findNearestAddr(pc, addr))
panic("could not find address %#x", pc);
if (is_call) { stack.push_back(addr);
if (!symtab->findNearestAddr(pc, addr)) pc = tc->readPC();
panic("could not find address %#x", pc); }
stack.push_back(addr); while (ksp > bottom) {
pc = tc->readPC(); Addr addr;
} 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;
Addr ra; Addr ra;
int size; int size;
if (decodePrologue(ksp, pc, addr, size, ra)) {
while (ksp > bottom) { if (!ra)
if (!symtab->findNearestAddr(pc, addr))
panic("could not find symbol for pc=%#x", pc);
assert(pc >= addr && "symbol botch: callpc < func");
stack.push_back(addr);
if (isEntry(addr))
return; return;
if (decodePrologue(ksp, pc, addr, size, ra)) { if (size <= 0) {
if (!ra)
return;
if (size <= 0) {
stack.push_back(unknown);
return;
}
pc = ra;
ksp += size;
} else {
stack.push_back(unknown); stack.push_back(unknown);
return; return;
} }
bool kernel = tc->getSystemPtr()->kernelStart <= pc && pc = ra;
pc <= tc->getSystemPtr()->kernelEnd; ksp += size;
if (!kernel) } else {
return; stack.push_back(unknown);
return;
if (stack.size() >= 1000)
panic("unwinding too far");
} }
panic("unwinding too far"); bool kernel = sys->kernelStart <= pc && pc <= sys->kernelEnd;
if (!kernel)
return;
if (stack.size() >= 1000)
panic("unwinding too far");
} }
bool panic("unwinding too far");
StackTrace::isEntry(Addr addr) }
{
if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp12))
return true;
if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp7)) bool
return true; StackTrace::isEntry(Addr addr)
{
if (addr == tc->readMiscRegNoEffect(IPR_PALtemp12))
return true;
if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp11)) if (addr == tc->readMiscRegNoEffect(IPR_PALtemp7))
return true; return true;
if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp21)) if (addr == tc->readMiscRegNoEffect(IPR_PALtemp11))
return true; return true;
if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp9)) if (addr == tc->readMiscRegNoEffect(IPR_PALtemp21))
return true; return true;
if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp2)) if (addr == tc->readMiscRegNoEffect(IPR_PALtemp9))
return true; return true;
if (addr == tc->readMiscRegNoEffect(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 false;
} }
bool return true;
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 * Decode the function prologue for the function we're in, and note
// * which registers are stored where, and how large the stack frame is.
// Opcode<31:26> == 0x10 */
// RA<25:21> == 30 bool
// Lit<20:13> StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func, int &size,
// One<12> = 1 Addr &ra)
// Func<11:5> == 0x20 (addq) {
// Func<11:5> == 0x29 (subq) size = 0;
// RC<4:0> == 30 ra = 0;
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) for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) {
disp = -sext<16>(inst & lda_disp_mask); MachInst inst;
else if ((inst & intop_mask) == addq_pattern) CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst));
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; int reg, disp;
} if (decodeStack(inst, disp)) {
if (size) {
bool // panic("decoding frame size again");
StackTrace::decodeSave(MachInst inst, int &reg, int &disp) return true;
{ }
// lda $stq, disp($sp) size += disp;
// } else if (decodeSave(inst, reg, disp)) {
// Opcode<31:26> == 0x08 if (!ra && reg == ReturnAddressReg) {
// RA<25:21> == ? CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr));
// RB<20:16> == 30 if (!ra) {
// Disp<15:0> // panic("no return address value pc=%#x\n", pc);
const MachInst stq_mask = 0xfc1f0000; return false;
const MachInst stq_pattern = 0xb41e0000;
const MachInst stq_disp_mask = 0x0000ffff;
const MachInst reg_mask = 0x03e00000;
const int reg_shift = 21;
if ((inst & stq_mask) == stq_pattern) {
reg = (inst & reg_mask) >> reg_shift;
disp = sext<16>(inst & stq_disp_mask);
} else {
return false;
}
return true;
}
/*
* Decode the function prologue for the function we're in, and note
* which registers are stored where, and how large the stack frame is.
*/
bool
StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
int &size, Addr &ra)
{
size = 0;
ra = 0;
for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) {
MachInst inst;
CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst));
int reg, disp;
if (decodeStack(inst, disp)) {
if (size) {
// panic("decoding frame size again");
return true;
}
size += disp;
} else if (decodeSave(inst, reg, disp)) {
if (!ra && reg == ReturnAddressReg) {
CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr));
if (!ra) {
// panic("no return address value pc=%#x\n", pc);
return false;
}
} }
} }
} }
return true;
} }
return true;
}
#if TRACING_ON #if TRACING_ON
void void
StackTrace::dump() StackTrace::dump()
{ {
StringWrap name(tc->getCpuPtr()->name()); StringWrap name(tc->getCpuPtr()->name());
SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
DPRINTFN("------ Stack ------\n"); DPRINTFN("------ Stack ------\n");
string symbol; string symbol;
for (int i = 0, size = stack.size(); i < size; ++i) { for (int i = 0, size = stack.size(); i < size; ++i) {
Addr addr = stack[size - i - 1]; Addr addr = stack[size - i - 1];
if (addr == user) if (addr == user)
symbol = "user"; symbol = "user";
else if (addr == console) else if (addr == console)
symbol = "console"; symbol = "console";
else if (addr == unknown) else if (addr == unknown)
symbol = "unknown"; symbol = "unknown";
else else
symtab->findSymbol(addr, symbol); symtab->findSymbol(addr, symbol);
DPRINTFN("%#x: %s\n", addr, symbol); DPRINTFN("%#x: %s\n", addr, symbol);
}
} }
#endif
} }
#endif
} // namespace AlphaISA

View file

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

View file

@ -42,8 +42,7 @@
#include "params/AlphaSystem.hh" #include "params/AlphaSystem.hh"
#include "sim/byteswap.hh" #include "sim/byteswap.hh"
using namespace AlphaISA;
using namespace LittleEndianGuest;
AlphaSystem::AlphaSystem(Params *p) AlphaSystem::AlphaSystem(Params *p)
: System(p) : System(p)
@ -67,8 +66,8 @@ AlphaSystem::AlphaSystem(Params *p)
// Load program sections into memory // Load program sections into memory
pal->loadSections(&functionalPort, AlphaISA::LoadAddrMask); pal->loadSections(&functionalPort, LoadAddrMask);
console->loadSections(&functionalPort, AlphaISA::LoadAddrMask); console->loadSections(&functionalPort, LoadAddrMask);
// load symbols // load symbols
if (!console->loadGlobalSymbols(consoleSymtab)) if (!console->loadGlobalSymbols(consoleSymtab))
@ -117,7 +116,6 @@ AlphaSystem::AlphaSystem(Params *p)
virtPort.write(addr+0x58, data); virtPort.write(addr+0x58, data);
} else } else
panic("could not find hwrpb\n"); panic("could not find hwrpb\n");
} }
AlphaSystem::~AlphaSystem() AlphaSystem::~AlphaSystem()
@ -142,9 +140,9 @@ AlphaSystem::~AlphaSystem()
* in the procedure value register (pv aka t12 == r27). This sequence * in the procedure value register (pv aka t12 == r27). This sequence
* looks like the following: * looks like the following:
* *
* opcode Ra Rb offset * opcode Ra Rb offset
* ldah gp,X(pv) 09 29 27 X * ldah gp,X(pv) 09 29 27 X
* lda gp,Y(gp) 08 29 29 Y * lda gp,Y(gp) 08 29 29 Y
* *
* for some constant offsets X and Y. The catch is that the linker * for some constant offsets X and Y. The catch is that the linker
* (or maybe even the compiler, I'm not sure) may recognize that the * (or maybe even the compiler, I'm not sure) may recognize that the
@ -172,11 +170,11 @@ AlphaSystem::fixFuncEventAddr(Addr addr)
const uint32_t gp_lda_pattern = (8 << 26) | (29 << 21) | (29 << 16); const uint32_t gp_lda_pattern = (8 << 26) | (29 << 21) | (29 << 16);
uint32_t i1 = virtPort.read<uint32_t>(addr); uint32_t i1 = virtPort.read<uint32_t>(addr);
uint32_t i2 = virtPort.read<uint32_t>(addr + sizeof(AlphaISA::MachInst)); uint32_t i2 = virtPort.read<uint32_t>(addr + sizeof(MachInst));
if ((i1 & inst_mask) == gp_ldah_pattern && if ((i1 & inst_mask) == gp_ldah_pattern &&
(i2 & inst_mask) == gp_lda_pattern) { (i2 & inst_mask) == gp_lda_pattern) {
Addr new_addr = addr + 2* sizeof(AlphaISA::MachInst); Addr new_addr = addr + 2 * sizeof(MachInst);
DPRINTF(Loader, "fixFuncEventAddr: %p -> %p", addr, new_addr); DPRINTF(Loader, "fixFuncEventAddr: %p -> %p", addr, new_addr);
return new_addr; return new_addr;
} else { } else {
@ -184,15 +182,15 @@ AlphaSystem::fixFuncEventAddr(Addr addr)
} }
} }
void void
AlphaSystem::setAlphaAccess(Addr access) AlphaSystem::setAlphaAccess(Addr access)
{ {
Addr addr = 0; Addr addr = 0;
if (consoleSymtab->findAddress("m5AlphaAccess", addr)) { if (consoleSymtab->findAddress("m5AlphaAccess", addr)) {
virtPort.write(addr, htog(EV5::Phys2K0Seg(access))); virtPort.write(addr, htog(Phys2K0Seg(access)));
} else } else {
panic("could not find m5AlphaAccess\n"); panic("could not find m5AlphaAccess\n");
}
} }
void void
@ -203,7 +201,6 @@ AlphaSystem::serialize(std::ostream &os)
palSymtab->serialize("pal_symtab", os); palSymtab->serialize("pal_symtab", os);
} }
void void
AlphaSystem::unserialize(Checkpoint *cp, const std::string &section) AlphaSystem::unserialize(Checkpoint *cp, const std::string &section)
{ {

View file

@ -49,10 +49,10 @@ class AlphaSystem : public System
AlphaSystem(Params *p); AlphaSystem(Params *p);
~AlphaSystem(); ~AlphaSystem();
/**
* Serialization stuff
*/
public: public:
/**
* Serialization stuff
*/
virtual void serialize(std::ostream &os); virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section); virtual void unserialize(Checkpoint *cp, const std::string &section);
@ -77,26 +77,28 @@ class AlphaSystem : public System
/** Event to halt the simulator if the console calls panic() */ /** Event to halt the simulator if the console calls panic() */
BreakPCEvent *consolePanicEvent; BreakPCEvent *consolePanicEvent;
#endif #endif
protected: protected:
const Params *params() const { return (const Params *)_params; } const Params *params() const { return (const Params *)_params; }
/** Add a function-based event to PALcode. */ /** Add a function-based event to PALcode. */
template <class T> template <class T>
T *addPalFuncEvent(const char *lbl) T *
addPalFuncEvent(const char *lbl)
{ {
return addFuncEvent<T>(palSymtab, lbl); return addFuncEvent<T>(palSymtab, lbl);
} }
/** Add a function-based event to the console code. */ /** Add a function-based event to the console code. */
template <class T> template <class T>
T *addConsoleFuncEvent(const char *lbl) T *
addConsoleFuncEvent(const char *lbl)
{ {
return addFuncEvent<T>(consoleSymtab, lbl); return addFuncEvent<T>(consoleSymtab, lbl);
} }
virtual Addr fixFuncEventAddr(Addr addr); virtual Addr fixFuncEventAddr(Addr addr);
}; };
#endif #endif // __ARCH_ALPHA_SYSTEM_HH__

View file

@ -43,19 +43,20 @@
#include "cpu/thread_context.hh" #include "cpu/thread_context.hh"
using namespace std; using namespace std;
using namespace EV5;
namespace AlphaISA { namespace AlphaISA {
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// //
// Alpha TLB // Alpha TLB
// //
#ifdef DEBUG #ifdef DEBUG
bool uncacheBit39 = false; bool uncacheBit39 = false;
bool uncacheBit40 = false; bool uncacheBit40 = false;
#endif #endif
#define MODE2MASK(X) (1 << (X)) #define MODE2MASK(X) (1 << (X))
TLB::TLB(const Params *p) TLB::TLB(const Params *p)
: BaseTLB(p), size(p->size), nlu(0) : BaseTLB(p), size(p->size), nlu(0)
@ -114,20 +115,20 @@ TLB::lookup(Addr vpn, uint8_t asn)
return retval; return retval;
} }
Fault Fault
TLB::checkCacheability(RequestPtr &req) TLB::checkCacheability(RequestPtr &req, bool itb)
{ {
// in Alpha, cacheability is controlled by upper-level bits of the // in Alpha, cacheability is controlled by upper-level bits of the
// physical address // physical address
/* /*
* We support having the uncacheable bit in either bit 39 or bit 40. * We support having the uncacheable bit in either bit 39 or bit
* The Turbolaser platform (and EV5) support having the bit in 39, but * 40. The Turbolaser platform (and EV5) support having the bit
* Tsunami (which Linux assumes uses an EV6) generates accesses with * in 39, but Tsunami (which Linux assumes uses an EV6) generates
* the bit in 40. So we must check for both, but we have debug flags * accesses with the bit in 40. So we must check for both, but we
* to catch a weird case where both are used, which shouldn't happen. * have debug flags to catch a weird case where both are used,
*/ * which shouldn't happen.
*/
#if ALPHA_TLASER #if ALPHA_TLASER
@ -141,13 +142,20 @@ TLB::checkCacheability(RequestPtr &req)
return new UnimpFault("IPR memory space not implemented!"); return new UnimpFault("IPR memory space not implemented!");
} else { } else {
// mark request as uncacheable // mark request as uncacheable
req->setFlags(req->getFlags() | UNCACHEABLE); req->setFlags(Request::UNCACHEABLE);
#if !ALPHA_TLASER #if !ALPHA_TLASER
// Clear bits 42:35 of the physical address (10-2 in Tsunami manual) // Clear bits 42:35 of the physical address (10-2 in
// Tsunami manual)
req->setPaddr(req->getPaddr() & PAddrUncachedMask); req->setPaddr(req->getPaddr() & PAddrUncachedMask);
#endif #endif
} }
// We shouldn't be able to read from an uncachable address in Alpha as
// we don't have a ROM and we don't want to try to fetch from a device
// register as we destroy any data that is clear-on-read.
if (req->isUncacheable() && itb)
return new UnimpFault("CPU trying to fetch from uncached I/O");
} }
return NoFault; return NoFault;
} }
@ -216,7 +224,8 @@ TLB::flushProcesses()
++i; ++i;
if (!entry->asma) { if (!entry->asma) {
DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, entry->tag, entry->ppn); DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index,
entry->tag, entry->ppn);
entry->valid = false; entry->valid = false;
lookupTable.erase(cur); lookupTable.erase(cur);
} }
@ -279,7 +288,6 @@ TLB::unserialize(Checkpoint *cp, const string &section)
} }
} }
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// //
// Alpha ITB // Alpha ITB
@ -308,13 +316,12 @@ ITB::regStats()
accesses = hits + misses; accesses = hits + misses;
} }
Fault Fault
ITB::translate(RequestPtr &req, ThreadContext *tc) ITB::translateAtomic(RequestPtr req, ThreadContext *tc)
{ {
//If this is a pal pc, then set PHYSICAL //If this is a pal pc, then set PHYSICAL
if(FULL_SYSTEM && PcPAL(req->getPC())) if (FULL_SYSTEM && PcPAL(req->getPC()))
req->setFlags(req->getFlags() | PHYSICAL); req->setFlags(Request::PHYSICAL);
if (PcPAL(req->getPC())) { if (PcPAL(req->getPC())) {
// strip off PAL PC marker (lsb is 1) // strip off PAL PC marker (lsb is 1)
@ -323,7 +330,7 @@ ITB::translate(RequestPtr &req, ThreadContext *tc)
return NoFault; return NoFault;
} }
if (req->getFlags() & PHYSICAL) { if (req->getFlags() & Request::PHYSICAL) {
req->setPaddr(req->getVaddr()); req->setPaddr(req->getVaddr());
} else { } else {
// verify that this is a good virtual address // verify that this is a good virtual address
@ -390,15 +397,23 @@ ITB::translate(RequestPtr &req, ThreadContext *tc)
if (req->getPaddr() & ~PAddrImplMask) if (req->getPaddr() & ~PAddrImplMask)
return genMachineCheckFault(); return genMachineCheckFault();
return checkCacheability(req); return checkCacheability(req, true);
} }
void
ITB::translateTiming(RequestPtr req, ThreadContext *tc,
Translation *translation)
{
assert(translation);
translation->finish(translateAtomic(req, tc), req, tc, false);
}
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// //
// Alpha DTB // Alpha DTB
// //
DTB::DTB(const Params *p) DTB::DTB(const Params *p)
: TLB(p) : TLB(p)
{} {}
@ -472,14 +487,13 @@ DTB::regStats()
} }
Fault Fault
DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) DTB::translateAtomic(RequestPtr req, ThreadContext *tc, bool write)
{ {
Addr pc = tc->readPC(); Addr pc = tc->readPC();
mode_type mode = mode_type mode =
(mode_type)DTB_CM_CM(tc->readMiscRegNoEffect(IPR_DTB_CM)); (mode_type)DTB_CM_CM(tc->readMiscRegNoEffect(IPR_DTB_CM));
/** /**
* Check for alignment faults * Check for alignment faults
*/ */
@ -491,13 +505,13 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
} }
if (PcPAL(pc)) { if (PcPAL(pc)) {
mode = (req->getFlags() & ALTMODE) ? mode = (req->getFlags() & Request::ALTMODE) ?
(mode_type)ALT_MODE_AM( (mode_type)ALT_MODE_AM(
tc->readMiscRegNoEffect(IPR_ALT_MODE)) tc->readMiscRegNoEffect(IPR_ALT_MODE))
: mode_kernel; : mode_kernel;
} }
if (req->getFlags() & PHYSICAL) { if (req->getFlags() & Request::PHYSICAL) {
req->setPaddr(req->getVaddr()); req->setPaddr(req->getVaddr());
} else { } else {
// verify that this is a good virtual address // verify that this is a good virtual address
@ -517,14 +531,15 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) if (VAddrSpaceEV6(req->getVaddr()) == 0x7e)
#endif #endif
{ {
// only valid in kernel mode // only valid in kernel mode
if (DTB_CM_CM(tc->readMiscRegNoEffect(IPR_DTB_CM)) != if (DTB_CM_CM(tc->readMiscRegNoEffect(IPR_DTB_CM)) !=
mode_kernel) { mode_kernel) {
if (write) { write_acv++; } else { read_acv++; } if (write) { write_acv++; } else { read_acv++; }
uint64_t flags = ((write ? MM_STAT_WR_MASK : 0) | uint64_t flags = ((write ? MM_STAT_WR_MASK : 0) |
MM_STAT_ACV_MASK); MM_STAT_ACV_MASK);
return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags);
return new DtbAcvFault(req->getVaddr(), req->getFlags(),
flags);
} }
req->setPaddr(req->getVaddr() & PAddrImplMask); req->setPaddr(req->getVaddr() & PAddrImplMask);
@ -553,7 +568,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
if (write) { write_misses++; } else { read_misses++; } if (write) { write_misses++; } else { read_misses++; }
uint64_t flags = (write ? MM_STAT_WR_MASK : 0) | uint64_t flags = (write ? MM_STAT_WR_MASK : 0) |
MM_STAT_DTB_MISS_MASK; MM_STAT_DTB_MISS_MASK;
return (req->getFlags() & VPTE) ? return (req->getFlags() & Request::VPTE) ?
(Fault)(new PDtbMissFault(req->getVaddr(), req->getFlags(), (Fault)(new PDtbMissFault(req->getVaddr(), req->getFlags(),
flags)) : flags)) :
(Fault)(new NDtbMissFault(req->getVaddr(), req->getFlags(), (Fault)(new NDtbMissFault(req->getVaddr(), req->getFlags(),
@ -570,25 +585,28 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
uint64_t flags = MM_STAT_WR_MASK | uint64_t flags = MM_STAT_WR_MASK |
MM_STAT_ACV_MASK | MM_STAT_ACV_MASK |
(entry->fonw ? MM_STAT_FONW_MASK : 0); (entry->fonw ? MM_STAT_FONW_MASK : 0);
return new DtbPageFault(req->getVaddr(), req->getFlags(), flags); return new DtbPageFault(req->getVaddr(), req->getFlags(),
flags);
} }
if (entry->fonw) { if (entry->fonw) {
write_acv++; write_acv++;
uint64_t flags = MM_STAT_WR_MASK | uint64_t flags = MM_STAT_WR_MASK | MM_STAT_FONW_MASK;
MM_STAT_FONW_MASK; return new DtbPageFault(req->getVaddr(), req->getFlags(),
return new DtbPageFault(req->getVaddr(), req->getFlags(), flags); flags);
} }
} else { } else {
if (!(entry->xre & MODE2MASK(mode))) { if (!(entry->xre & MODE2MASK(mode))) {
read_acv++; read_acv++;
uint64_t flags = MM_STAT_ACV_MASK | uint64_t flags = MM_STAT_ACV_MASK |
(entry->fonr ? MM_STAT_FONR_MASK : 0); (entry->fonr ? MM_STAT_FONR_MASK : 0);
return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags); return new DtbAcvFault(req->getVaddr(), req->getFlags(),
flags);
} }
if (entry->fonr) { if (entry->fonr) {
read_acv++; read_acv++;
uint64_t flags = MM_STAT_FONR_MASK; uint64_t flags = MM_STAT_FONR_MASK;
return new DtbPageFault(req->getVaddr(), req->getFlags(), flags); return new DtbPageFault(req->getVaddr(), req->getFlags(),
flags);
} }
} }
} }
@ -606,6 +624,14 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
return checkCacheability(req); return checkCacheability(req);
} }
void
DTB::translateTiming(RequestPtr req, ThreadContext *tc,
Translation *translation, bool write)
{
assert(translation);
translation->finish(translateAtomic(req, tc, write), req, tc, write);
}
TlbEntry & TlbEntry &
TLB::index(bool advance) TLB::index(bool advance)
{ {

View file

@ -29,8 +29,8 @@
* Steve Reinhardt * Steve Reinhardt
*/ */
#ifndef __ALPHA_MEMORY_HH__ #ifndef __ARCH_ALPHA_TLB_HH__
#define __ALPHA_MEMORY_HH__ #define __ARCH_ALPHA_TLB_HH__
#include <map> #include <map>
@ -48,110 +48,120 @@
class ThreadContext; class ThreadContext;
namespace AlphaISA namespace AlphaISA {
class TlbEntry;
class TLB : public BaseTLB
{ {
class TlbEntry; protected:
typedef std::multimap<Addr, int> PageTable;
PageTable lookupTable; // Quick lookup into page table
class TLB : public BaseTLB TlbEntry *table; // the Page Table
int size; // TLB Size
int nlu; // not last used entry (for replacement)
void nextnlu() { if (++nlu >= size) nlu = 0; }
TlbEntry *lookup(Addr vpn, uint8_t asn);
public:
typedef AlphaTLBParams Params;
TLB(const Params *p);
virtual ~TLB();
int getsize() const { return size; }
TlbEntry &index(bool advance = true);
void insert(Addr vaddr, TlbEntry &entry);
void flushAll();
void flushProcesses();
void flushAddr(Addr addr, uint8_t asn);
void
demapPage(Addr vaddr, uint64_t asn)
{ {
protected: assert(asn < (1 << 8));
typedef std::multimap<Addr, int> PageTable; flushAddr(vaddr, asn);
PageTable lookupTable; // Quick lookup into page table }
TlbEntry *table; // the Page Table // static helper functions... really EV5 VM traits
int size; // TLB Size static bool
int nlu; // not last used entry (for replacement) validVirtualAddress(Addr vaddr)
void nextnlu() { if (++nlu >= size) nlu = 0; }
TlbEntry *lookup(Addr vpn, uint8_t asn);
public:
typedef AlphaTLBParams Params;
TLB(const Params *p);
virtual ~TLB();
int getsize() const { return size; }
TlbEntry &index(bool advance = true);
void insert(Addr vaddr, TlbEntry &entry);
void flushAll();
void flushProcesses();
void flushAddr(Addr addr, uint8_t asn);
void demapPage(Addr vaddr, uint64_t asn)
{
assert(asn < (1 << 8));
flushAddr(vaddr, asn);
}
// 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);
}
static Fault checkCacheability(RequestPtr &req);
// Checkpointing
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
// Most recently used page table entries
TlbEntry *EntryCache[3];
inline void flushCache()
{
memset(EntryCache, 0, 3 * sizeof(TlbEntry*));
}
inline TlbEntry* updateCache(TlbEntry *entry) {
EntryCache[2] = EntryCache[1];
EntryCache[1] = EntryCache[0];
EntryCache[0] = entry;
return entry;
}
};
class ITB : public TLB
{ {
protected: // unimplemented bits must be all 0 or all 1
mutable Stats::Scalar<> hits; Addr unimplBits = vaddr & VAddrUnImplMask;
mutable Stats::Scalar<> misses; return unimplBits == 0 || unimplBits == VAddrUnImplMask;
mutable Stats::Scalar<> acv; }
mutable Stats::Formula accesses;
public: static Fault checkCacheability(RequestPtr &req, bool itb = false);
typedef AlphaITBParams Params;
ITB(const Params *p);
virtual void regStats();
Fault translate(RequestPtr &req, ThreadContext *tc); // Checkpointing
}; virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
class DTB : public TLB // Most recently used page table entries
TlbEntry *EntryCache[3];
inline void
flushCache()
{ {
protected: memset(EntryCache, 0, 3 * sizeof(TlbEntry*));
mutable Stats::Scalar<> read_hits; }
mutable Stats::Scalar<> read_misses;
mutable Stats::Scalar<> read_acv;
mutable Stats::Scalar<> read_accesses;
mutable Stats::Scalar<> write_hits;
mutable Stats::Scalar<> write_misses;
mutable Stats::Scalar<> write_acv;
mutable Stats::Scalar<> write_accesses;
Stats::Formula hits;
Stats::Formula misses;
Stats::Formula acv;
Stats::Formula accesses;
public: inline TlbEntry *
typedef AlphaDTBParams Params; updateCache(TlbEntry *entry) {
DTB(const Params *p); EntryCache[2] = EntryCache[1];
virtual void regStats(); EntryCache[1] = EntryCache[0];
EntryCache[0] = entry;
return entry;
}
};
Fault translate(RequestPtr &req, ThreadContext *tc, bool write); class ITB : public TLB
}; {
} protected:
mutable Stats::Scalar hits;
mutable Stats::Scalar misses;
mutable Stats::Scalar acv;
mutable Stats::Formula accesses;
#endif // __ALPHA_MEMORY_HH__ public:
typedef AlphaITBParams Params;
ITB(const Params *p);
virtual void regStats();
Fault translateAtomic(RequestPtr req, ThreadContext *tc);
void translateTiming(RequestPtr req, ThreadContext *tc,
Translation *translation);
};
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;
public:
typedef AlphaDTBParams Params;
DTB(const Params *p);
virtual void regStats();
Fault translateAtomic(RequestPtr req, ThreadContext *tc, bool write);
void translateTiming(RequestPtr req, ThreadContext *tc,
Translation *translation, bool write);
};
} // namespace AlphaISA
#endif // __ARCH_ALPHA_TLB_HH__

View file

@ -32,10 +32,8 @@
#include "arch/alpha/tru64/tru64.hh" #include "arch/alpha/tru64/tru64.hh"
#include "arch/alpha/isa_traits.hh" #include "arch/alpha/isa_traits.hh"
#include "arch/alpha/tru64/process.hh" #include "arch/alpha/tru64/process.hh"
#include "cpu/thread_context.hh" #include "cpu/thread_context.hh"
#include "kern/tru64/tru64.hh" #include "kern/tru64/tru64.hh"
#include "sim/process.hh" #include "sim/process.hh"
#include "sim/syscall_emul.hh" #include "sim/syscall_emul.hh"
@ -47,7 +45,7 @@ static SyscallReturn
unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc) ThreadContext *tc)
{ {
TypedBufferArg<AlphaTru64::utsname> name(tc->getSyscallArg(0)); TypedBufferArg<AlphaTru64::utsname> name(process->getSyscallArg(tc, 0));
strcpy(name->sysname, "OSF1"); strcpy(name->sysname, "OSF1");
strcpy(name->nodename, "m5.eecs.umich.edu"); strcpy(name->nodename, "m5.eecs.umich.edu");
@ -64,34 +62,35 @@ static SyscallReturn
getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc) ThreadContext *tc)
{ {
unsigned op = tc->getSyscallArg(0); unsigned op = process->getSyscallArg(tc, 0);
unsigned nbytes = tc->getSyscallArg(2); unsigned nbytes = process->getSyscallArg(tc, 2);
switch (op) { switch (op) {
case AlphaTru64::GSI_MAX_CPU: { case AlphaTru64::GSI_MAX_CPU: {
TypedBufferArg<uint32_t> max_cpu(tc->getSyscallArg(1)); TypedBufferArg<uint32_t> max_cpu(process->getSyscallArg(tc, 1));
*max_cpu = htog((uint32_t)process->numCpus()); *max_cpu = htog((uint32_t)process->numCpus());
max_cpu.copyOut(tc->getMemPort()); max_cpu.copyOut(tc->getMemPort());
return 1; return 1;
} }
case AlphaTru64::GSI_CPUS_IN_BOX: { case AlphaTru64::GSI_CPUS_IN_BOX: {
TypedBufferArg<uint32_t> cpus_in_box(tc->getSyscallArg(1)); TypedBufferArg<uint32_t> cpus_in_box(process->getSyscallArg(tc, 1));
*cpus_in_box = htog((uint32_t)process->numCpus()); *cpus_in_box = htog((uint32_t)process->numCpus());
cpus_in_box.copyOut(tc->getMemPort()); cpus_in_box.copyOut(tc->getMemPort());
return 1; return 1;
} }
case AlphaTru64::GSI_PHYSMEM: { case AlphaTru64::GSI_PHYSMEM: {
TypedBufferArg<uint64_t> physmem(tc->getSyscallArg(1)); TypedBufferArg<uint64_t> physmem(process->getSyscallArg(tc, 1));
*physmem = htog((uint64_t)1024 * 1024); // physical memory in KB *physmem = htog((uint64_t)1024 * 1024); // physical memory in KB
physmem.copyOut(tc->getMemPort()); physmem.copyOut(tc->getMemPort());
return 1; return 1;
} }
case AlphaTru64::GSI_CPU_INFO: { case AlphaTru64::GSI_CPU_INFO: {
TypedBufferArg<AlphaTru64::cpu_info> infop(tc->getSyscallArg(1)); TypedBufferArg<AlphaTru64::cpu_info>
infop(process->getSyscallArg(tc, 1));
infop->current_cpu = htog(0); infop->current_cpu = htog(0);
infop->cpus_in_box = htog(process->numCpus()); infop->cpus_in_box = htog(process->numCpus());
@ -108,14 +107,14 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
} }
case AlphaTru64::GSI_PROC_TYPE: { case AlphaTru64::GSI_PROC_TYPE: {
TypedBufferArg<uint64_t> proc_type(tc->getSyscallArg(1)); TypedBufferArg<uint64_t> proc_type(process->getSyscallArg(tc, 1));
*proc_type = htog((uint64_t)11); *proc_type = htog((uint64_t)11);
proc_type.copyOut(tc->getMemPort()); proc_type.copyOut(tc->getMemPort());
return 1; return 1;
} }
case AlphaTru64::GSI_PLATFORM_NAME: { case AlphaTru64::GSI_PLATFORM_NAME: {
BufferArg bufArg(tc->getSyscallArg(1), nbytes); BufferArg bufArg(process->getSyscallArg(tc, 1), nbytes);
strncpy((char *)bufArg.bufferPtr(), strncpy((char *)bufArg.bufferPtr(),
"COMPAQ Professional Workstation XP1000", "COMPAQ Professional Workstation XP1000",
nbytes); nbytes);
@ -124,7 +123,7 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
} }
case AlphaTru64::GSI_CLK_TCK: { case AlphaTru64::GSI_CLK_TCK: {
TypedBufferArg<uint64_t> clk_hz(tc->getSyscallArg(1)); TypedBufferArg<uint64_t> clk_hz(process->getSyscallArg(tc, 1));
*clk_hz = htog((uint64_t)1024); *clk_hz = htog((uint64_t)1024);
clk_hz.copyOut(tc->getMemPort()); clk_hz.copyOut(tc->getMemPort());
return 1; return 1;
@ -143,12 +142,12 @@ static SyscallReturn
setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc) ThreadContext *tc)
{ {
unsigned op = tc->getSyscallArg(0); unsigned op = process->getSyscallArg(tc, 0);
switch (op) { switch (op) {
case AlphaTru64::SSI_IEEE_FP_CONTROL: case AlphaTru64::SSI_IEEE_FP_CONTROL:
warn("setsysinfo: ignoring ieee_set_fp_control() arg 0x%x\n", warn("setsysinfo: ignoring ieee_set_fp_control() arg 0x%x\n",
tc->getSyscallArg(1)); process->getSyscallArg(tc, 1));
break; break;
default: default:
@ -159,26 +158,24 @@ setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
return 0; return 0;
} }
/// Target table() handler. /// Target table() handler.
static static SyscallReturn
SyscallReturn tableFunc(SyscallDesc *desc, int callnum, LiveProcess *process, tableFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc) ThreadContext *tc)
{ {
using namespace std; using namespace std;
using namespace TheISA;
int id = tc->getSyscallArg(0); // table ID int id = process->getSyscallArg(tc, 0); // table ID
int index = tc->getSyscallArg(1); // index into table int index = process->getSyscallArg(tc, 1); // index into table
// arg 2 is buffer pointer; type depends on table ID // arg 2 is buffer pointer; type depends on table ID
int nel = tc->getSyscallArg(3); // number of elements int nel = process->getSyscallArg(tc, 3); // number of elements
int lel = tc->getSyscallArg(4); // expected element size int lel = process->getSyscallArg(tc, 4); // expected element size
switch (id) { switch (id) {
case AlphaTru64::TBL_SYSINFO: { case AlphaTru64::TBL_SYSINFO: {
if (index != 0 || nel != 1 || lel != sizeof(Tru64::tbl_sysinfo)) if (index != 0 || nel != 1 || lel != sizeof(Tru64::tbl_sysinfo))
return -EINVAL; return -EINVAL;
TypedBufferArg<Tru64::tbl_sysinfo> elp(tc->getSyscallArg(2)); TypedBufferArg<Tru64::tbl_sysinfo> elp(process->getSyscallArg(tc, 2));
const int clk_hz = one_million; const int clk_hz = one_million;
elp->si_user = htog(curTick / (Clock::Frequency / clk_hz)); elp->si_user = htog(curTick / (Clock::Frequency / clk_hz));
@ -219,7 +216,7 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = {
/* 14 */ SyscallDesc("mknod", unimplementedFunc), /* 14 */ SyscallDesc("mknod", unimplementedFunc),
/* 15 */ SyscallDesc("chmod", unimplementedFunc), /* 15 */ SyscallDesc("chmod", unimplementedFunc),
/* 16 */ SyscallDesc("chown", unimplementedFunc), /* 16 */ SyscallDesc("chown", unimplementedFunc),
/* 17 */ SyscallDesc("obreak", obreakFunc), /* 17 */ SyscallDesc("obreak", brkFunc),
/* 18 */ SyscallDesc("pre_F64_getfsstat", unimplementedFunc), /* 18 */ SyscallDesc("pre_F64_getfsstat", unimplementedFunc),
/* 19 */ SyscallDesc("lseek", lseekFunc), /* 19 */ SyscallDesc("lseek", lseekFunc),
/* 20 */ SyscallDesc("getpid", getpidPseudoFunc), /* 20 */ SyscallDesc("getpid", getpidPseudoFunc),
@ -260,9 +257,9 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = {
/* 55 */ SyscallDesc("reboot", unimplementedFunc), /* 55 */ SyscallDesc("reboot", unimplementedFunc),
/* 56 */ SyscallDesc("revoke", unimplementedFunc), /* 56 */ SyscallDesc("revoke", unimplementedFunc),
/* 57 */ SyscallDesc("symlink", unimplementedFunc), /* 57 */ SyscallDesc("symlink", unimplementedFunc),
/* 58 */ SyscallDesc("readlink", unimplementedFunc), /* 58 */ SyscallDesc("readlink", readlinkFunc),
/* 59 */ SyscallDesc("execve", unimplementedFunc), /* 59 */ SyscallDesc("execve", unimplementedFunc),
/* 60 */ SyscallDesc("umask", unimplementedFunc), /* 60 */ SyscallDesc("umask", umaskFunc),
/* 61 */ SyscallDesc("chroot", unimplementedFunc), /* 61 */ SyscallDesc("chroot", unimplementedFunc),
/* 62 */ SyscallDesc("old_fstat", unimplementedFunc), /* 62 */ SyscallDesc("old_fstat", unimplementedFunc),
/* 63 */ SyscallDesc("getpgrp", unimplementedFunc), /* 63 */ SyscallDesc("getpgrp", unimplementedFunc),
@ -339,7 +336,7 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = {
/* 133 */ SyscallDesc("sendto", unimplementedFunc), /* 133 */ SyscallDesc("sendto", unimplementedFunc),
/* 134 */ SyscallDesc("shutdown", unimplementedFunc), /* 134 */ SyscallDesc("shutdown", unimplementedFunc),
/* 135 */ SyscallDesc("socketpair", unimplementedFunc), /* 135 */ SyscallDesc("socketpair", unimplementedFunc),
/* 136 */ SyscallDesc("mkdir", unimplementedFunc), /* 136 */ SyscallDesc("mkdir", mkdirFunc),
/* 137 */ SyscallDesc("rmdir", unimplementedFunc), /* 137 */ SyscallDesc("rmdir", unimplementedFunc),
/* 138 */ SyscallDesc("utimes", unimplementedFunc), /* 138 */ SyscallDesc("utimes", unimplementedFunc),
/* 139 */ SyscallDesc("obsolete 4.2 sigreturn", unimplementedFunc), /* 139 */ SyscallDesc("obsolete 4.2 sigreturn", unimplementedFunc),
@ -472,15 +469,14 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = {
/* 266 */ SyscallDesc("sendfile", unimplementedFunc), /* 266 */ SyscallDesc("sendfile", unimplementedFunc),
}; };
SyscallDesc AlphaTru64Process::machSyscallDescs[] = { SyscallDesc AlphaTru64Process::machSyscallDescs[] = {
/* 0 */ SyscallDesc("kern_invalid", unimplementedFunc), /* 0 */ SyscallDesc("kern_invalid", unimplementedFunc),
/* 1 */ SyscallDesc("m5_mutex_lock", AlphaTru64::m5_mutex_lockFunc), /* 1 */ SyscallDesc("m5_mutex_lock", AlphaTru64::m5_mutex_lockFunc),
/* 2 */ SyscallDesc("m5_mutex_trylock", AlphaTru64::m5_mutex_trylockFunc), /* 2 */ SyscallDesc("m5_mutex_trylock", AlphaTru64::m5_mutex_trylockFunc),
/* 3 */ SyscallDesc("m5_mutex_unlock", AlphaTru64::m5_mutex_unlockFunc), /* 3 */ SyscallDesc("m5_mutex_unlock", AlphaTru64::m5_mutex_unlockFunc),
/* 4 */ SyscallDesc("m5_cond_signal", AlphaTru64::m5_cond_signalFunc), /* 4 */ SyscallDesc("m5_cond_signal", AlphaTru64::m5_cond_signalFunc),
/* 5 */ SyscallDesc("m5_cond_broadcast", AlphaTru64::m5_cond_broadcastFunc), /* 5 */ SyscallDesc("m5_cond_broadcast",
AlphaTru64::m5_cond_broadcastFunc),
/* 6 */ SyscallDesc("m5_cond_wait", AlphaTru64::m5_cond_waitFunc), /* 6 */ SyscallDesc("m5_cond_wait", AlphaTru64::m5_cond_waitFunc),
/* 7 */ SyscallDesc("m5_thread_exit", AlphaTru64::m5_thread_exitFunc), /* 7 */ SyscallDesc("m5_thread_exit", AlphaTru64::m5_thread_exitFunc),
/* 8 */ SyscallDesc("kern_invalid", unimplementedFunc), /* 8 */ SyscallDesc("kern_invalid", unimplementedFunc),
@ -507,7 +503,8 @@ SyscallDesc AlphaTru64Process::machSyscallDescs[] = {
/* 29 */ SyscallDesc("nxm_thread_destroy", unimplementedFunc), /* 29 */ SyscallDesc("nxm_thread_destroy", unimplementedFunc),
/* 30 */ SyscallDesc("lw_wire", unimplementedFunc), /* 30 */ SyscallDesc("lw_wire", unimplementedFunc),
/* 31 */ SyscallDesc("lw_unwire", unimplementedFunc), /* 31 */ SyscallDesc("lw_unwire", unimplementedFunc),
/* 32 */ SyscallDesc("nxm_thread_create", AlphaTru64::nxm_thread_createFunc), /* 32 */ SyscallDesc("nxm_thread_create",
AlphaTru64::nxm_thread_createFunc),
/* 33 */ SyscallDesc("nxm_task_init", AlphaTru64::nxm_task_initFunc), /* 33 */ SyscallDesc("nxm_task_init", AlphaTru64::nxm_task_initFunc),
/* 34 */ SyscallDesc("kern_invalid", unimplementedFunc), /* 34 */ SyscallDesc("kern_invalid", unimplementedFunc),
/* 35 */ SyscallDesc("nxm_idle", AlphaTru64::nxm_idleFunc), /* 35 */ SyscallDesc("nxm_idle", AlphaTru64::nxm_idleFunc),
@ -572,9 +569,8 @@ AlphaTru64Process::getDesc(int callnum)
return &syscallDescs[callnum]; return &syscallDescs[callnum];
} }
AlphaTru64Process::AlphaTru64Process(LiveProcessParams *params,
AlphaTru64Process::AlphaTru64Process(LiveProcessParams * params, ObjectFile *objFile)
ObjectFile *objFile)
: AlphaLiveProcess(params, objFile), : AlphaLiveProcess(params, objFile),
Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)), Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)),
Num_Mach_Syscall_Descs(sizeof(machSyscallDescs) / sizeof(SyscallDesc)) Num_Mach_Syscall_Descs(sizeof(machSyscallDescs) / sizeof(SyscallDesc))

View file

@ -28,12 +28,13 @@
* Authors: Steve Reinhardt * Authors: Steve Reinhardt
*/ */
#ifndef __ALPHA_TRU64_PROCESS_HH__ #ifndef __ARCH_ALPHA_TRU64_PROCESS_HH__
#define __ALPHA_TRU64_PROCESS_HH__ #define __ARCH_ALPHA_TRU64_PROCESS_HH__
#include "arch/alpha/process.hh" #include "arch/alpha/process.hh"
namespace AlphaISA { namespace AlphaISA {
/// A process with emulated Alpha Tru64 syscalls. /// A process with emulated Alpha Tru64 syscalls.
class AlphaTru64Process : public AlphaLiveProcess class AlphaTru64Process : public AlphaLiveProcess
{ {
@ -51,9 +52,9 @@ class AlphaTru64Process : public AlphaLiveProcess
const int Num_Syscall_Descs; const int Num_Syscall_Descs;
const int Num_Mach_Syscall_Descs; const int Num_Mach_Syscall_Descs;
virtual SyscallDesc* getDesc(int callnum); virtual SyscallDesc *getDesc(int callnum);
}; };
} // namespace AlphaISA } // namespace AlphaISA
#endif // __ALPHA_TRU64_PROCESS_HH__ #endif // __ARCH_ALPHA_TRU64_PROCESS_HH__

View file

@ -33,34 +33,34 @@
// open(2) flags translation table // open(2) flags translation table
OpenFlagTransTable AlphaTru64::openFlagTable[] = { OpenFlagTransTable AlphaTru64::openFlagTable[] = {
#ifdef _MSC_VER #ifdef _MSC_VER
{ AlphaTru64::TGT_O_RDONLY, _O_RDONLY }, { AlphaTru64::TGT_O_RDONLY, _O_RDONLY },
{ AlphaTru64::TGT_O_WRONLY, _O_WRONLY }, { AlphaTru64::TGT_O_WRONLY, _O_WRONLY },
{ AlphaTru64::TGT_O_RDWR, _O_RDWR }, { AlphaTru64::TGT_O_RDWR, _O_RDWR },
{ AlphaTru64::TGT_O_APPEND, _O_APPEND }, { AlphaTru64::TGT_O_APPEND, _O_APPEND },
{ AlphaTru64::TGT_O_CREAT, _O_CREAT }, { AlphaTru64::TGT_O_CREAT, _O_CREAT },
{ AlphaTru64::TGT_O_TRUNC, _O_TRUNC }, { AlphaTru64::TGT_O_TRUNC, _O_TRUNC },
{ AlphaTru64::TGT_O_EXCL, _O_EXCL }, { AlphaTru64::TGT_O_EXCL, _O_EXCL },
#ifdef _O_NONBLOCK #ifdef _O_NONBLOCK
{ AlphaTru64::TGT_O_NONBLOCK, _O_NONBLOCK }, { AlphaTru64::TGT_O_NONBLOCK, _O_NONBLOCK },
#endif #endif
#ifdef _O_NOCTTY #ifdef _O_NOCTTY
{ AlphaTru64::TGT_O_NOCTTY, _O_NOCTTY }, { AlphaTru64::TGT_O_NOCTTY, _O_NOCTTY },
#endif #endif
#ifdef _O_SYNC #ifdef _O_SYNC
{ AlphaTru64::TGT_O_SYNC, _O_SYNC }, { AlphaTru64::TGT_O_SYNC, _O_SYNC },
#endif #endif
#else /* !_MSC_VER */ #else /* !_MSC_VER */
{ AlphaTru64::TGT_O_RDONLY, O_RDONLY }, { AlphaTru64::TGT_O_RDONLY, O_RDONLY },
{ AlphaTru64::TGT_O_WRONLY, O_WRONLY }, { AlphaTru64::TGT_O_WRONLY, O_WRONLY },
{ AlphaTru64::TGT_O_RDWR, O_RDWR }, { AlphaTru64::TGT_O_RDWR, O_RDWR },
{ AlphaTru64::TGT_O_APPEND, O_APPEND }, { AlphaTru64::TGT_O_APPEND, O_APPEND },
{ AlphaTru64::TGT_O_CREAT, O_CREAT }, { AlphaTru64::TGT_O_CREAT, O_CREAT },
{ AlphaTru64::TGT_O_TRUNC, O_TRUNC }, { AlphaTru64::TGT_O_TRUNC, O_TRUNC },
{ AlphaTru64::TGT_O_EXCL, O_EXCL }, { AlphaTru64::TGT_O_EXCL, O_EXCL },
{ AlphaTru64::TGT_O_NONBLOCK, O_NONBLOCK }, { AlphaTru64::TGT_O_NONBLOCK, O_NONBLOCK },
{ AlphaTru64::TGT_O_NOCTTY, O_NOCTTY }, { AlphaTru64::TGT_O_NOCTTY, O_NOCTTY },
#ifdef O_SYNC #ifdef O_SYNC
{ AlphaTru64::TGT_O_SYNC, O_SYNC }, { AlphaTru64::TGT_O_SYNC, O_SYNC },
#endif #endif
#endif /* _MSC_VER */ #endif /* _MSC_VER */
}; };

View file

@ -28,14 +28,13 @@
* Authors: Korey Sewell * Authors: Korey Sewell
*/ */
#ifndef __ALPHA_ALPHA_TRU64_HH #ifndef __ALPHA_ALPHA_TRU64_TRU64_HH__
#define __ALPHA_ALPHA_TRU64_HH #define __ALPHA_ALPHA_TRU64_TRU64_HH__
#include "kern/tru64/tru64.hh" #include "kern/tru64/tru64.hh"
class AlphaTru64 : public Tru64 class AlphaTru64 : public Tru64
{ {
public: public:
/// This table maps the target open() flags to the corresponding /// This table maps the target open() flags to the corresponding
/// host open() flags. /// host open() flags.
@ -46,21 +45,21 @@ class AlphaTru64 : public Tru64
//@{ //@{
/// open(2) flag values. /// open(2) flag values.
static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY
static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY
static const int TGT_O_RDWR = 00000002; //!< O_RDWR static const int TGT_O_RDWR = 00000002; //!< O_RDWR
static const int TGT_O_NONBLOCK = 00000004; //!< O_NONBLOCK static const int TGT_O_NONBLOCK = 00000004; //!< O_NONBLOCK
static const int TGT_O_APPEND = 00000010; //!< O_APPEND static const int TGT_O_APPEND = 00000010; //!< O_APPEND
static const int TGT_O_CREAT = 00001000; //!< O_CREAT static const int TGT_O_CREAT = 00001000; //!< O_CREAT
static const int TGT_O_TRUNC = 00002000; //!< O_TRUNC static const int TGT_O_TRUNC = 00002000; //!< O_TRUNC
static const int TGT_O_EXCL = 00004000; //!< O_EXCL static const int TGT_O_EXCL = 00004000; //!< O_EXCL
static const int TGT_O_NOCTTY = 00010000; //!< O_NOCTTY static const int TGT_O_NOCTTY = 00010000; //!< O_NOCTTY
static const int TGT_O_SYNC = 00040000; //!< O_SYNC static const int TGT_O_SYNC = 00040000; //!< O_SYNC
static const int TGT_O_DRD = 00100000; //!< O_DRD static const int TGT_O_DRD = 00100000; //!< O_DRD
static const int TGT_O_DIRECTIO = 00200000; //!< O_DIRECTIO static const int TGT_O_DIRECTIO = 00200000; //!< O_DIRECTIO
static const int TGT_O_CACHE = 00400000; //!< O_CACHE static const int TGT_O_CACHE = 00400000; //!< O_CACHE
static const int TGT_O_DSYNC = 02000000; //!< O_DSYNC static const int TGT_O_DSYNC = 02000000; //!< O_DSYNC
static const int TGT_O_RSYNC = 04000000; //!< O_RSYNC static const int TGT_O_RSYNC = 04000000; //!< O_RSYNC
//@} //@}
/// For mmap(). /// For mmap().
@ -68,13 +67,13 @@ class AlphaTru64 : public Tru64
//@{ //@{
/// For getsysinfo(). /// For getsysinfo().
static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name string
static const unsigned GSI_CPU_INFO = 59; //!< CPU information static const unsigned GSI_CPU_INFO = 59; //!< CPU information
static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type
static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine static const unsigned GSI_MAX_CPU = 30; //!< max # CPUs on machine
static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system
static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB
static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz
//@} //@}
//@{ //@{
@ -124,6 +123,4 @@ class AlphaTru64 : public Tru64
}; };
}; };
#endif // __ALPHA_ALPHA_TRU64_TRU64_HH__
#endif

View file

@ -32,47 +32,43 @@
#ifndef __ARCH_ALPHA_TYPES_HH__ #ifndef __ARCH_ALPHA_TYPES_HH__
#define __ARCH_ALPHA_TYPES_HH__ #define __ARCH_ALPHA_TYPES_HH__
#include <inttypes.h> #include "sim/host.hh"
namespace AlphaISA namespace AlphaISA {
typedef uint32_t MachInst;
typedef uint64_t ExtMachInst;
typedef uint8_t RegIndex;
typedef uint64_t IntReg;
typedef uint64_t LargestRead;
// floating point register file entry type
typedef double FloatReg;
typedef uint64_t FloatRegBits;
// control register file contents
typedef uint64_t MiscReg;
union AnyReg
{ {
IntReg intreg;
FloatReg fpreg;
MiscReg ctrlreg;
};
typedef uint32_t MachInst; enum annotes
typedef uint64_t ExtMachInst; {
typedef uint8_t RegIndex; ANNOTE_NONE = 0,
// An impossible number for instruction annotations
ITOUCH_ANNOTE = 0xffffffff,
};
typedef uint64_t IntReg; struct CoreSpecific
typedef uint64_t LargestRead; {
int core_type;
};
// floating point register file entry type
typedef double FloatReg;
typedef uint64_t FloatRegBits;
// control register file contents
typedef uint64_t MiscReg;
typedef union {
IntReg intreg;
FloatReg fpreg;
MiscReg ctrlreg;
} AnyReg;
enum RegContextParam
{
CONTEXT_PALMODE
};
typedef bool RegContextVal;
enum annotes {
ANNOTE_NONE = 0,
// An impossible number for instruction annotations
ITOUCH_ANNOTE = 0xffffffff,
};
struct CoreSpecific {
int core_type;
};
} // namespace AlphaISA } // namespace AlphaISA
#endif #endif // __ARCH_ALPHA_TYPES_HH__

View file

@ -36,28 +36,28 @@
#include "mem/vport.hh" #include "mem/vport.hh"
#endif #endif
namespace AlphaISA namespace AlphaISA {
{
uint64_t getArgument(ThreadContext *tc, int number, bool fp) uint64_t
getArgument(ThreadContext *tc, int number, bool fp)
{ {
#if FULL_SYSTEM #if FULL_SYSTEM
const int NumArgumentRegs = 6;
if (number < NumArgumentRegs) { if (number < NumArgumentRegs) {
if (fp) if (fp)
return tc->readFloatRegBits(ArgumentReg[number]); return tc->readFloatRegBits(16 + number);
else else
return tc->readIntReg(ArgumentReg[number]); return tc->readIntReg(16 + number);
} else { } else {
Addr sp = tc->readIntReg(StackPointerReg); Addr sp = tc->readIntReg(StackPointerReg);
VirtualPort *vp = tc->getVirtPort(tc); VirtualPort *vp = tc->getVirtPort();
uint64_t arg = vp->read<uint64_t>(sp + uint64_t arg = vp->read<uint64_t>(sp +
(number-NumArgumentRegs) * sizeof(uint64_t)); (number-NumArgumentRegs) * sizeof(uint64_t));
tc->delVirtPort(vp);
return arg; return arg;
} }
#else #else
panic("getArgument() is Full system only\n"); panic("getArgument() is Full system only\n");
M5_DUMMY_RETURN M5_DUMMY_RETURN;
#endif #endif
} }

View file

@ -32,127 +32,137 @@
#ifndef __ARCH_ALPHA_UTILITY_HH__ #ifndef __ARCH_ALPHA_UTILITY_HH__
#define __ARCH_ALPHA_UTILITY_HH__ #define __ARCH_ALPHA_UTILITY_HH__
#include "config/full_system.hh"
#include "arch/alpha/types.hh" #include "arch/alpha/types.hh"
#include "arch/alpha/isa_traits.hh" #include "arch/alpha/isa_traits.hh"
#include "arch/alpha/regfile.hh" #include "arch/alpha/regfile.hh"
#include "base/misc.hh" #include "base/misc.hh"
#include "config/full_system.hh"
#include "cpu/thread_context.hh" #include "cpu/thread_context.hh"
namespace AlphaISA namespace AlphaISA {
uint64_t getArgument(ThreadContext *tc, int number, bool fp);
inline bool
inUserMode(ThreadContext *tc)
{ {
return (tc->readMiscRegNoEffect(IPR_DTB_CM) & 0x18) != 0;
}
uint64_t getArgument(ThreadContext *tc, int number, bool fp); inline bool
isCallerSaveIntegerRegister(unsigned int reg)
{
panic("register classification not implemented");
return (reg >= 1 && reg <= 8) || (reg >= 22 && reg <= 25) || reg == 27;
}
static inline bool inline bool
inUserMode(ThreadContext *tc) isCalleeSaveIntegerRegister(unsigned int reg)
{ {
return (tc->readMiscRegNoEffect(AlphaISA::IPR_DTB_CM) & 0x18) != 0; panic("register classification not implemented");
} return reg >= 9 && reg <= 15;
}
inline bool isCallerSaveIntegerRegister(unsigned int reg) { inline bool
panic("register classification not implemented"); isCallerSaveFloatRegister(unsigned int reg)
return (reg >= 1 && reg <= 8 || reg >= 22 && reg <= 25 || reg == 27); {
} panic("register classification not implemented");
return false;
}
inline bool isCalleeSaveIntegerRegister(unsigned int reg) { inline bool
panic("register classification not implemented"); isCalleeSaveFloatRegister(unsigned int reg)
return (reg >= 9 && reg <= 15); {
} panic("register classification not implemented");
return false;
}
inline bool isCallerSaveFloatRegister(unsigned int reg) { inline Addr
panic("register classification not implemented"); alignAddress(const Addr &addr, unsigned int nbytes)
return false; {
} return (addr & ~(nbytes - 1));
}
inline bool isCalleeSaveFloatRegister(unsigned int reg) { // Instruction address compression hooks
panic("register classification not implemented"); inline Addr
return false; realPCToFetchPC(const Addr &addr)
} {
return addr;
}
inline Addr alignAddress(const Addr &addr, inline Addr
unsigned int nbytes) { fetchPCToRealPC(const Addr &addr)
return (addr & ~(nbytes - 1)); {
} return addr;
}
// Instruction address compression hooks // the size of "fetched" instructions (not necessarily the size
inline Addr realPCToFetchPC(const Addr &addr) { // of real instructions for PISA)
return addr; inline size_t
} fetchInstSize()
{
return sizeof(MachInst);
}
inline Addr fetchPCToRealPC(const Addr &addr) { inline MachInst
return addr; makeRegisterCopy(int dest, int src)
} {
panic("makeRegisterCopy not implemented");
return 0;
}
// the size of "fetched" instructions (not necessarily the size // Machine operations
// of real instructions for PISA) void saveMachineReg(AnyReg &savereg, const RegFile &reg_file, int regnum);
inline size_t fetchInstSize() { void restoreMachineReg(RegFile &regs, const AnyReg &reg, int regnum);
return sizeof(MachInst);
}
inline MachInst makeRegisterCopy(int dest, int src) { /**
panic("makeRegisterCopy not implemented"); * Function to insure ISA semantics about 0 registers.
return 0; * @param tc The thread context.
} */
template <class TC>
void zeroRegisters(TC *tc);
// Machine operations // Alpha IPR register accessors
inline bool PcPAL(Addr addr) { return addr & 0x3; }
inline void startupCPU(ThreadContext *tc, int cpuId) { tc->activate(0); }
void saveMachineReg(AnyReg &savereg, const RegFile &reg_file, ////////////////////////////////////////////////////////////////////////
int regnum); //
// Translation stuff
//
void restoreMachineReg(RegFile &regs, const AnyReg &reg, inline Addr PteAddr(Addr a) { return (a & PteMask) << PteShift; }
int regnum);
/** // User Virtual
* Function to insure ISA semantics about 0 registers. inline bool IsUSeg(Addr a) { return USegBase <= a && a <= USegEnd; }
* @param tc The thread context.
*/
template <class TC>
void zeroRegisters(TC *tc);
// Alpha IPR register accessors // Kernel Direct Mapped
inline bool PcPAL(Addr addr) { return addr & 0x3; } inline bool IsK0Seg(Addr a) { return K0SegBase <= a && a <= K0SegEnd; }
inline void startupCPU(ThreadContext *tc, int cpuId) { inline Addr K0Seg2Phys(Addr addr) { return addr & ~K0SegBase; }
tc->activate(0);
}
//////////////////////////////////////////////////////////////////////// // Kernel Virtual
// inline bool IsK1Seg(Addr a) { return K1SegBase <= a && a <= K1SegEnd; }
// Translation stuff
//
inline Addr PteAddr(Addr a) { return (a & PteMask) << PteShift; } inline Addr
TruncPage(Addr addr)
{ return addr & ~(PageBytes - 1); }
// User Virtual inline Addr
inline bool IsUSeg(Addr a) { return USegBase <= a && a <= USegEnd; } RoundPage(Addr addr)
{ return (addr + PageBytes - 1) & ~(PageBytes - 1); }
// Kernel Direct Mapped void initIPRs(ThreadContext *tc, int cpuId);
inline bool IsK0Seg(Addr a) { return K0SegBase <= a && a <= K0SegEnd; }
inline Addr K0Seg2Phys(Addr addr) { return addr & ~K0SegBase; }
// Kernel Virtual
inline bool IsK1Seg(Addr a) { return K1SegBase <= a && a <= K1SegEnd; }
inline Addr
TruncPage(Addr addr)
{ return addr & ~(PageBytes - 1); }
inline Addr
RoundPage(Addr addr)
{ return (addr + PageBytes - 1) & ~(PageBytes - 1); }
void initIPRs(ThreadContext *tc, int cpuId);
#if FULL_SYSTEM #if FULL_SYSTEM
void initCPU(ThreadContext *tc, int cpuId); void initCPU(ThreadContext *tc, int cpuId);
/** /**
* Function to check for and process any interrupts. * Function to check for and process any interrupts.
* @param tc The thread context. * @param tc The thread context.
*/ */
template <class TC> template <class TC>
void processInterrupts(TC *tc); void processInterrupts(TC *tc);
#endif #endif
} // namespace AlphaISA } // namespace AlphaISA
#endif #endif // __ARCH_ALPHA_UTILITY_HH__

View file

@ -40,27 +40,28 @@
#include "mem/vport.hh" #include "mem/vport.hh"
using namespace std; using namespace std;
using namespace AlphaISA;
AlphaISA::PageTableEntry namespace AlphaISA {
AlphaISA::kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vaddr)
PageTableEntry
kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, VAddr vaddr)
{ {
Addr level1_pte = ptbr + vaddr.level1(); Addr level1_pte = ptbr + vaddr.level1();
AlphaISA::PageTableEntry level1 = mem->read<uint64_t>(level1_pte); PageTableEntry level1 = mem->read<uint64_t>(level1_pte);
if (!level1.valid()) { if (!level1.valid()) {
DPRINTF(VtoPhys, "level 1 PTE not valid, va = %#\n", vaddr); DPRINTF(VtoPhys, "level 1 PTE not valid, va = %#\n", vaddr);
return 0; return 0;
} }
Addr level2_pte = level1.paddr() + vaddr.level2(); Addr level2_pte = level1.paddr() + vaddr.level2();
AlphaISA::PageTableEntry level2 = mem->read<uint64_t>(level2_pte); PageTableEntry level2 = mem->read<uint64_t>(level2_pte);
if (!level2.valid()) { if (!level2.valid()) {
DPRINTF(VtoPhys, "level 2 PTE not valid, va = %#x\n", vaddr); DPRINTF(VtoPhys, "level 2 PTE not valid, va = %#x\n", vaddr);
return 0; return 0;
} }
Addr level3_pte = level2.paddr() + vaddr.level3(); Addr level3_pte = level2.paddr() + vaddr.level3();
AlphaISA::PageTableEntry level3 = mem->read<uint64_t>(level3_pte); PageTableEntry level3 = mem->read<uint64_t>(level3_pte);
if (!level3.valid()) { if (!level3.valid()) {
DPRINTF(VtoPhys, "level 3 PTE not valid, va = %#x\n", vaddr); DPRINTF(VtoPhys, "level 3 PTE not valid, va = %#x\n", vaddr);
return 0; return 0;
@ -69,13 +70,13 @@ AlphaISA::kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vadd
} }
Addr Addr
AlphaISA::vtophys(Addr vaddr) vtophys(Addr vaddr)
{ {
Addr paddr = 0; Addr paddr = 0;
if (AlphaISA::IsUSeg(vaddr)) if (IsUSeg(vaddr))
DPRINTF(VtoPhys, "vtophys: invalid vaddr %#x", vaddr); DPRINTF(VtoPhys, "vtophys: invalid vaddr %#x", vaddr);
else if (AlphaISA::IsK0Seg(vaddr)) else if (IsK0Seg(vaddr))
paddr = AlphaISA::K0Seg2Phys(vaddr); paddr = K0Seg2Phys(vaddr);
else else
panic("vtophys: ptbr is not set on virtual lookup"); panic("vtophys: ptbr is not set on virtual lookup");
@ -85,22 +86,22 @@ AlphaISA::vtophys(Addr vaddr)
} }
Addr Addr
AlphaISA::vtophys(ThreadContext *tc, Addr addr) vtophys(ThreadContext *tc, Addr addr)
{ {
AlphaISA::VAddr vaddr = addr; VAddr vaddr = addr;
Addr ptbr = tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp20); Addr ptbr = tc->readMiscRegNoEffect(IPR_PALtemp20);
Addr paddr = 0; Addr paddr = 0;
//@todo Andrew couldn't remember why he commented some of this code //@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? //so I put it back in. Perhaps something to do with gdb debugging?
if (AlphaISA::PcPAL(vaddr) && (vaddr < EV5::PalMax)) { if (PcPAL(vaddr) && (vaddr < PalMax)) {
paddr = vaddr & ~ULL(1); paddr = vaddr & ~ULL(1);
} else { } else {
if (AlphaISA::IsK0Seg(vaddr)) { if (IsK0Seg(vaddr)) {
paddr = AlphaISA::K0Seg2Phys(vaddr); paddr = K0Seg2Phys(vaddr);
} else if (!ptbr) { } else if (!ptbr) {
paddr = vaddr; paddr = vaddr;
} else { } else {
AlphaISA::PageTableEntry pte = PageTableEntry pte =
kernel_pte_lookup(tc->getPhysPort(), ptbr, vaddr); kernel_pte_lookup(tc->getPhysPort(), ptbr, vaddr);
if (pte.valid()) if (pte.valid())
paddr = pte.paddr() | vaddr.offset(); paddr = pte.paddr() | vaddr.offset();
@ -113,3 +114,4 @@ AlphaISA::vtophys(ThreadContext *tc, Addr addr)
return paddr; return paddr;
} }
} // namespace AlphaISA

View file

@ -41,12 +41,13 @@ class FunctionalPort;
namespace AlphaISA { namespace AlphaISA {
PageTableEntry PageTableEntry kernel_pte_lookup(FunctionalPort *mem, Addr ptbr,
kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vaddr); VAddr vaddr);
Addr vtophys(Addr vaddr); Addr vtophys(Addr vaddr);
Addr vtophys(ThreadContext *tc, Addr vaddr); Addr vtophys(ThreadContext *tc, Addr vaddr);
} // namespace AlphaISA
};
#endif // __ARCH_ALPHA_VTOPHYS_H__ #endif // __ARCH_ALPHA_VTOPHYS_H__

View file

@ -34,25 +34,21 @@ from m5.params import *
class ArmTLB(SimObject): class ArmTLB(SimObject):
abstract = True abstract = True
type = 'ArmTLB' type = 'ArmTLB'
cxx_namespace = 'ArmISA' cxx_class = 'ArmISA::TLB'
cxx_class = 'TLB'
size = Param.Int("TLB size") size = Param.Int("TLB size")
class ArmDTB(ArmTLB): class ArmDTB(ArmTLB):
type = 'ArmDTB' type = 'ArmDTB'
cxx_namespace = 'ArmISA' cxx_class = 'ArmISA::DTB'
cxx_class = 'DTB'
size = 64 size = 64
class ArmITB(ArmTLB): class ArmITB(ArmTLB):
type = 'ArmITB' type = 'ArmITB'
cxx_namespace = 'ArmISA' cxx_class = 'ArmISA::ITB'
cxx_class = 'ITB'
size = 64 size = 64
class ArmUTB(ArmTLB): class ArmUTB(ArmTLB):
type = 'ArmUTB' type = 'ArmUTB'
cxx_namespace = 'ArmISA' cxx_class = 'ArmISA::UTB'
cxx_class = 'UTB'
size = 64 size = 64

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