AddrRange(Addr('2GB'), size ='256MB')]
self.bridge.master = self.iobus.slave
self.bridge.slave = self.membus.master
- self.rom.port = self.membus.master
- self.nvram.port = self.membus.master
- self.hypervisor_desc.port = self.membus.master
- self.partition_desc.port = self.membus.master
self.intrctrl = IntrControl()
self.disk0 = CowMmDisk()
self.disk0.childImage(mdesc.disks()[0])
AddrRange(self.t1000.hvuart.pio_addr,
self.t1000.hvuart.pio_addr + uart_pio_size - 1)
]
- self.reset_bin = binary('reset_new.bin')
- self.hypervisor_bin = binary('q_new.bin')
- self.openboot_bin = binary('openboot_new.bin')
- self.nvram_bin = binary('nvram1')
- self.hypervisor_desc_bin = binary('1up-hv.bin')
- self.partition_desc_bin = binary('1up-md.bin')
+
+ workload = SparcFsWorkload(
+ reset_bin=binary('reset_new.bin'),
+ hypervisor_bin=binary('q_new.bin'),
+ openboot_bin=binary('openboot_new.bin'),
+ nvram_bin=binary('nvram1'),
+ hypervisor_desc_bin=binary('1up-hv.bin'),
+ partition_desc_bin=binary('1up-md.bin'),
+ )
+
+ # ROM for OBP/Reset/Hypervisor
+ self.rom = SimpleMemory(range=AddrRange(workload._rom_base, size='8MB'))
+ # nvram
+ self.nvram = SimpleMemory(
+ range=AddrRange(workload._nvram_base, size='8kB'))
+ # hypervisor description
+ self.hypervisor_desc = SimpleMemory(
+ range=AddrRange(workload._hypervisor_desc_base, size='8kB'))
+ # partition description
+ self.partition_desc = SimpleMemory(
+ range=AddrRange(workload._partition_desc_base, size='8kB'))
+
+ self.rom.port = self.membus.master
+ self.nvram.port = self.membus.master
+ self.hypervisor_desc.port = self.membus.master
+ self.partition_desc.port = self.membus.master
self.system_port = self.membus.slave
+ self.workload = workload
+
return self
def makeArmSystem(mem_mode, machine_type, num_cpus=1, mdesc=None,
pci_devices = []
- if bare_metal:
- self = ArmSystem()
- else:
- self = LinuxArmSystem()
+ self = ArmSystem()
if not mdesc:
# generic system
# EOT character on UART will end the simulation
self.realview.uart[0].end_on_eot = True
else:
+ workload = ArmFsLinux()
+
if dtb_filename:
- self.dtb_filename = binary(dtb_filename)
+ workload.dtb_filename = binary(dtb_filename)
- self.machine_type = machine_type if machine_type in ArmMachineType.map \
- else "DTOnly"
+ workload.machine_type = \
+ machine_type if machine_type in ArmMachineType.map else "DTOnly"
# Ensure that writes to the UART actually go out early in the boot
if not cmdline:
'lpj=19988480 norandmaps rw loglevel=8 ' + \
'mem=%(mem)s root=%(rootdev)s'
- self.realview.setupBootLoader(self, binary, bootloader)
-
if hasattr(self.realview.gic, 'cpu_addr'):
self.gic_cpu_addr = self.realview.gic.cpu_addr
"androidboot.selinux=permissive " + \
"video=Virtual-1:1920x1080-16"
- self.boot_osflags = fillInCmdline(mdesc, cmdline)
+ workload.command_line = fillInCmdline(mdesc, cmdline)
+
+ self.workload = workload
+
+ self.realview.setupBootLoader(self, binary)
if external_memory:
# I/O traffic enters iobus
self.console = binary('mips/console')
if not cmdline:
cmdline = 'root=/dev/hda1 console=ttyS0'
- self.boot_osflags = fillInCmdline(mdesc, cmdline)
+ self.workload = OsKernel(command_line=fillInCmdline(mdesc, cmdline))
self.system_port = self.membus.slave
x86_sys.pc.attachIO(x86_sys.iobus, x86_sys._dma_ports)
-def makeX86System(mem_mode, numCPUs=1, mdesc=None, self=None, Ruby=False):
- if self == None:
- self = X86System()
+def makeX86System(mem_mode, numCPUs=1, mdesc=None, workload=None, Ruby=False):
+ self = X86System()
+
+ if workload is None:
+ workload = X86FsWorkload()
+ self.workload = workload
if not mdesc:
# generic system
# Add in a Bios information structure.
structures = [X86SMBiosBiosInformation()]
- self.smbios_table.structures = structures
+ workload.smbios_table.structures = structures
# Set up the Intel MP table
base_entries = []
self.pc.south_bridge.io_apic.apic_id = io_apic.id
base_entries.append(io_apic)
# In gem5 Pc::calcPciConfigAddr(), it required "assert(bus==0)",
- # but linux kernel cannot config PCI device if it was not connected to PCI bus,
- # so we fix PCI bus id to 0, and ISA bus id to 1.
+ # but linux kernel cannot config PCI device if it was not connected to
+ # PCI bus, so we fix PCI bus id to 0, and ISA bus id to 1.
pci_bus = X86IntelMPBus(bus_id = 0, bus_type='PCI ')
base_entries.append(pci_bus)
isa_bus = X86IntelMPBus(bus_id = 1, bus_type='ISA ')
assignISAInt(1, 1)
for i in range(3, 15):
assignISAInt(i, i)
- self.intel_mp_table.base_entries = base_entries
- self.intel_mp_table.ext_entries = ext_entries
+ workload.intel_mp_table.base_entries = base_entries
+ workload.intel_mp_table.ext_entries = ext_entries
+
+ return self
def makeLinuxX86System(mem_mode, numCPUs=1, mdesc=None, Ruby=False,
cmdline=None):
- self = LinuxX86System()
-
# Build up the x86 system and then specialize it for Linux
- makeX86System(mem_mode, numCPUs, mdesc, self, Ruby)
+ self = makeX86System(mem_mode, numCPUs, mdesc, X86FsLinux(), Ruby)
# We assume below that there's at least 1MB of memory. We'll require 2
# just to avoid corner cases.
entries.append(X86E820Entry(addr = 0x100000000,
size = '%dB' % (self.mem_ranges[1].size()), range_type = 1))
- self.e820_table.entries = entries
+ self.workload.e820_table.entries = entries
# Command line
if not cmdline:
cmdline = 'earlyprintk=ttyS0 console=ttyS0 lpj=7999923 root=/dev/hda1'
- self.boot_osflags = fillInCmdline(mdesc, cmdline)
+ self.workload.command_line = fillInCmdline(mdesc, cmdline)
return self
port_data=opt_tlm_memory,
port=system.membus.master,
addr_ranges=system.mem_ranges)
- system.kernel_addr_check = False
+ system.workload.addr_check = False
return
if opt_external_memory_system:
port_type=opt_external_memory_system,
port_data="init_mem0", port=xbar.master,
addr_ranges=system.mem_ranges)
- subsystem.kernel_addr_check = False
+ subsystem.workload.addr_check = False
return
nbr_mem_ctrls = opt_mem_channels
args.mem_size,
platform=VExpress_GEM5_V2(),
mem_mode=mem_mode,
- kernel=args.kernel,
+ workload=ArmFsWorkload(
+ object_file=args.kernel),
readfile=args.readfile)
MemConfig.config_mem(args, system)
if args.dtb_gen:
# No run, autogenerate DTB and exit
- root.system.generateDtb(m5.options.outdir, 'system.dtb')
+ root.system.generateDtb(os.path.join(m5.options.outdir, 'system.dtb'))
else:
run(args)
platform = ObjectList.platform_list.get(machine_type)
m5.util.inform("Simulated platform: %s", platform.__name__)
- sys = devices.simpleSystem(LinuxArmSystem,
+ sys = devices.simpleSystem(ArmSystem,
caches, mem_size, platform(),
- kernel=SysPaths.binary(kernel),
+ workload=ArmFsLinux(
+ object_file=SysPaths.binary(kernel)),
readfile=bootscript)
sys.mem_ctrls = [ SimpleMemory(range=r, port=sys.membus.master)
root.system = system
if options.kernel_cmd:
- system.boot_osflags = options.kernel_cmd
+ system.workload.command_line = options.kernel_cmd
else:
- system.boot_osflags = " ".join(kernel_cmd)
+ system.workload.command_line = " ".join(kernel_cmd)
if options.big_cpus + options.little_cpus == 0:
m5.util.panic("Empty CPU clusters")
# Linux device tree
if options.dtb is not None:
- system.dtb_filename = SysPaths.binary(options.dtb)
+ system.workload.dtb_filename = SysPaths.binary(options.dtb)
else:
- system.generateDtb(m5.options.outdir, 'system.dtb')
+ system.workload.dtb_filename = \
+ os.path.join(m5.options.outdir, 'system.dtb')
+ system.generateDtb(system.workload.dtb_filename)
if devices.have_fastmodel and issubclass(big_model, FastmodelCluster):
from m5 import arm_fast_model as fm, systemc as sc
# Only simulate caches when using a timing CPU (e.g., the HPI model)
want_caches = True if mem_mode == "timing" else False
- system = devices.simpleSystem(LinuxArmSystem,
+ system = devices.simpleSystem(ArmSystem,
want_caches,
args.mem_size,
mem_mode=mem_mode,
- kernel=SysPaths.binary(args.kernel),
+ workload=ArmFsLinux(
+ object_file=
+ SysPaths.binary(args.kernel)),
readfile=args.script)
MemConfig.config_mem(args, system)
system.realview.setupBootLoader(system, SysPaths.binary)
if args.dtb:
- system.dtb_filename = args.dtb
+ system.workload.dtb_filename = args.dtb
else:
# No DTB specified: autogenerate DTB
- system.generateDtb(m5.options.outdir, 'system.dtb')
+ system.workload.dtb_filename = \
+ os.path.join(m5.options.outdir, 'system.dtb')
+ system.generateDtb(system.workload.dtb_filename)
# Linux boot command flags
kernel_cmd = [
# memory layout.
"norandmaps",
# Tell Linux where to find the root disk image.
- "root=/dev/vda1",
+ "root=/dev/vda",
# Mount the root disk read-write by default.
"rw",
# Tell Linux about the amount of physical memory present.
"mem=%s" % args.mem_size,
]
- system.boot_osflags = " ".join(kernel_cmd)
+ system.workload.command_line = " ".join(kernel_cmd)
return system
test_sys.cpu_voltage_domain)
if options.kernel is not None:
- test_sys.kernel = binary(options.kernel)
+ test_sys.workload.object_file = binary(options.kernel)
if options.script is not None:
test_sys.readfile = options.script
drive_sys.cpu.createInterruptController()
drive_sys.cpu.connectAllPorts(drive_sys.membus)
if options.kernel is not None:
- drive_sys.kernel = binary(options.kernel)
+ drive_sys.workload.object_file = binary(options.kernel)
if ObjectList.is_kvm_cpu(DriveCPUClass):
drive_sys.kvm_vm = KvmVM()
for sysname in ('system', 'testsys', 'drivesys'):
if hasattr(root, sysname):
sys = getattr(root, sysname)
- sys.generateDtb(m5.options.outdir, '%s.dtb' % sysname)
+ sys.workload.dtb_filename = \
+ os.path.join(m5.options.outdir, '%s.dtb' % sysname)
+ sys.generateDtb(sys.workload.dtb_filename)
Simulation.setWorkCountOptions(test_sys, options)
Simulation.run(options, root, test_sys, FutureClass)
import m5
from m5.defines import buildEnv
from m5.objects import *
+from m5.params import NULL
from m5.util import addToPath, fatal, warn
addToPath('../')
system = System(cpu = [CPUClass(cpu_id=i) for i in range(np)],
mem_mode = test_mem_mode,
mem_ranges = [AddrRange(options.mem_size)],
- cache_line_size = options.cacheline_size)
+ cache_line_size = options.cacheline_size,
+ workload = NULL)
if numThreads > 1:
system.multi_thread = True
--- /dev/null
+# Copyright (c) 2009, 2012-2013, 2015-2019 ARM Limited
+# All rights reserved.
+#
+# The license below extends only to copyright in the software and shall
+# not be construed as granting a license to any other intellectual
+# property including but not limited to intellectual property relating
+# to a hardware implementation of the functionality of the software
+# licensed hereunder. You may use the software subject to the license
+# terms below provided that you ensure that this notice is replicated
+# unmodified and in its entirety in all distributions of the software,
+# modified or unmodified, in source code or in binary form.
+#
+# 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.
+
+from m5.params import *
+from m5.options import *
+from m5.SimObject import *
+from m5.objects.OsKernel import OsKernel
+
+class ArmMachineType(Enum):
+ map = {
+ 'VExpress_EMM' : 2272,
+ 'VExpress_EMM64' : 2272,
+ 'DTOnly' : -1,
+ }
+
+class ArmFsWorkload(OsKernel):
+ type = 'ArmFsWorkload'
+ cxx_header = "arch/arm/fs_workload.hh"
+ cxx_class = "ArmISA::FsWorkload"
+
+ load_addr_mask = 0
+
+ boot_loader = VectorParam.String([],
+ "File that contains the boot loader code. Zero or more files may be "
+ "specified. The first boot loader that matches the kernel's "
+ "architecture will be used.")
+
+ dtb_filename = Param.String("",
+ "File that contains the Device Tree Blob. Don't use DTB if empty.")
+
+ machine_type = Param.ArmMachineType('DTOnly',
+ "Machine id from http://www.arm.linux.org.uk/developer/machines/")
+ atags_addr = Param.Addr("Address where default atags structure should " \
+ "be written")
+ early_kernel_symbols = Param.Bool(False,
+ "enable early kernel symbol tables before MMU")
+ enable_context_switch_stats_dump = Param.Bool(False,
+ "enable stats/task info dumping at context switch boundaries")
+
+ panic_on_panic = Param.Bool(False, "Trigger a gem5 panic if the " \
+ "guest kernel panics")
+ panic_on_oops = Param.Bool(False, "Trigger a gem5 panic if the " \
+ "guest kernel oopses")
+
+class ArmFsLinux(ArmFsWorkload):
+ type = 'ArmFsLinux'
+ cxx_header = "arch/arm/linux/fs_workload.hh"
+ cxx_class = "ArmISA::FsLinux"
+
+ @cxxMethod
+ def dumpDmesg(self):
+ """Dump dmesg from the simulated kernel to standard out"""
+ pass
+
+class ArmFsFreebsd(ArmFsWorkload):
+ type = 'ArmFsFreebsd'
+ cxx_header = "arch/arm/freebsd/fs_workload.hh"
+ cxx_class = "ArmISA::FsFreebsd"
from m5.objects.System import System
from m5.objects.ArmSemihosting import ArmSemihosting
-class ArmMachineType(Enum):
- map = {
- 'VExpress_EMM' : 2272,
- 'VExpress_EMM64' : 2272,
- 'DTOnly' : -1,
- }
-
class SveVectorLength(UInt8): min = 1; max = 16
class ArmSystem(System):
type = 'ArmSystem'
cxx_header = "arch/arm/system.hh"
multi_proc = Param.Bool(True, "Multiprocessor system?")
- boot_loader = VectorParam.String([],
- "File that contains the boot loader code. Zero or more files may be "
- "specified. The first boot loader that matches the kernel's "
- "architecture will be used.")
gic_cpu_addr = Param.Addr(0, "Addres of the GIC CPU interface")
flags_addr = Param.Addr(0, "Address of the flags register for MP booting")
have_security = Param.Bool(False,
semihosting = Param.ArmSemihosting(NULL,
"Enable support for the Arm semihosting by settings this parameter")
- dtb_filename = Param.String("",
- "File that contains the Device Tree Blob. Don't use DTB if empty.")
+ m5ops_base = Param.Addr(0,
+ "Base of the 64KiB PA range used for memory-mapped m5ops. Set to 0 "
+ "to disable.")
- def generateDtb(self, outdir, filename):
+ def generateDtb(self, filename):
"""
Autogenerate DTB. Arguments are the folder where the DTB
will be stored, and the name of the DTB file.
fdt = Fdt()
fdt.add_rootnode(rootNode)
- dtb_filename = os.path.join(outdir, filename)
- self.dtb_filename = fdt.writeDtbFile(dtb_filename)
+ fdt.writeDtbFile(filename)
def generateDeviceTree(self, state):
root.append(node)
return root
-
-class GenericArmSystem(ArmSystem):
- type = 'GenericArmSystem'
- cxx_header = "arch/arm/system.hh"
- machine_type = Param.ArmMachineType('DTOnly',
- "Machine id from http://www.arm.linux.org.uk/developer/machines/")
- atags_addr = Param.Addr("Address where default atags structure should " \
- "be written")
- early_kernel_symbols = Param.Bool(False,
- "enable early kernel symbol tables before MMU")
- enable_context_switch_stats_dump = Param.Bool(False,
- "enable stats/task info dumping at context switch boundaries")
-
- panic_on_panic = Param.Bool(False, "Trigger a gem5 panic if the " \
- "guest kernel panics")
- panic_on_oops = Param.Bool(False, "Trigger a gem5 panic if the " \
- "guest kernel oopses")
-
-class LinuxArmSystem(GenericArmSystem):
- type = 'LinuxArmSystem'
- cxx_header = "arch/arm/linux/system.hh"
-
- @cxxMethod
- def dumpDmesg(self):
- """Dump dmesg from the simulated kernel to standard out"""
- pass
-
- # Have Linux systems for ARM auto-calc their load_addr_mask for proper
- # kernel relocation.
- load_addr_mask = 0x0
-
-class FreebsdArmSystem(GenericArmSystem):
- type = 'FreebsdArmSystem'
- cxx_header = "arch/arm/freebsd/system.hh"
Source('isa_device.cc')
Source('linux/linux.cc')
Source('linux/process.cc')
- Source('linux/system.cc')
+ Source('linux/fs_workload.cc')
Source('freebsd/freebsd.cc')
Source('freebsd/process.cc')
- Source('freebsd/system.cc')
+ Source('freebsd/fs_workload.cc')
+ Source('fs_workload.cc')
Source('miscregs.cc')
Source('nativetrace.cc')
Source('pauth_helpers.cc')
Source('utility.cc')
Source('vtophys.cc')
+ SimObject('ArmFsWorkload.py')
SimObject('ArmInterrupts.py')
SimObject('ArmISA.py')
SimObject('ArmNativeTrace.py')
--- /dev/null
+/*
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * This software was developed by the University of Cambridge Computer
+ * Laboratory as part of the CTSRD Project, with support from the UK Higher
+ * Education Innovation Fund (HEIF).
+ *
+ * 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.
+ */
+
+#include "arch/arm/freebsd/fs_workload.hh"
+
+#include "arch/arm/isa_traits.hh"
+#include "arch/arm/utility.hh"
+#include "arch/generic/freebsd/threadinfo.hh"
+#include "base/loader/dtb_file.hh"
+#include "base/loader/object_file.hh"
+#include "base/loader/symtab.hh"
+#include "cpu/base.hh"
+#include "cpu/pc_event.hh"
+#include "cpu/thread_context.hh"
+#include "debug/Loader.hh"
+#include "kern/freebsd/events.hh"
+#include "mem/fs_translating_port_proxy.hh"
+#include "mem/physical.hh"
+#include "sim/stat_control.hh"
+
+using namespace FreeBSD;
+
+namespace ArmISA
+{
+
+FsFreebsd::FsFreebsd(Params *p) : ArmISA::FsWorkload(p),
+ enableContextSwitchStatsDump(p->enable_context_switch_stats_dump)
+{
+ if (p->panic_on_panic) {
+ kernelPanicEvent = addKernelFuncEventOrPanic<PanicPCEvent>(
+ "panic", "Kernel panic in simulated kernel");
+ } else {
+#ifndef NDEBUG
+ kernelPanicEvent = addKernelFuncEventOrPanic<BreakPCEvent>("panic");
+#endif
+ }
+
+ if (p->panic_on_oops) {
+ kernelOopsEvent = addKernelFuncEventOrPanic<PanicPCEvent>(
+ "oops_exit", "Kernel oops in guest");
+ }
+
+ uDelaySkipEvent = addKernelFuncEvent<UDelayEvent>(
+ "DELAY", "DELAY", 1000, 0);
+}
+
+void
+FsFreebsd::initState()
+{
+ ArmISA::FsWorkload::initState();
+
+ // Load symbols at physical address, we might not want
+ // to do this permanently, for but early bootup work
+ // it is helpful.
+ if (params()->early_kernel_symbols) {
+ obj->loadGlobalSymbols(symtab, 0, 0, loadAddrMask);
+ obj->loadGlobalSymbols(debugSymbolTable, 0, 0, loadAddrMask);
+ }
+
+ // Check if the kernel image has a symbol that tells us it supports
+ // device trees.
+ Addr addr;
+ fatal_if(!symtab->findAddress("fdt_get_range", addr),
+ "Kernel must have fdt support.");
+ fatal_if(params()->dtb_filename == "", "dtb file is not specified.");
+
+ // Kernel supports flattened device tree and dtb file specified.
+ // Using Device Tree Blob to describe system configuration.
+ inform("Loading DTB file: %s at address %#x\n", params()->dtb_filename,
+ params()->atags_addr + loadAddrOffset);
+
+ DtbFile *dtb_file = new DtbFile(params()->dtb_filename);
+
+ warn_if(!dtb_file->addBootCmdLine(commandLine.c_str(), commandLine.size()),
+ "Couldn't append bootargs to DTB file: %s",
+ params()->dtb_filename);
+
+ Addr ra = dtb_file->findReleaseAddr();
+ if (ra)
+ bootReleaseAddr = ra & ~ULL(0x7F);
+
+ dtb_file->buildImage().
+ offset(params()->atags_addr + loadAddrOffset).
+ write(system->physProxy);
+ delete dtb_file;
+
+ // Kernel boot requirements to set up r0, r1 and r2 in ARMv7
+ for (auto tc: system->threadContexts) {
+ tc->setIntReg(0, 0);
+ tc->setIntReg(1, params()->machine_type);
+ tc->setIntReg(2, params()->atags_addr + loadAddrOffset);
+ }
+}
+
+FsFreebsd::~FsFreebsd()
+{
+ delete uDelaySkipEvent;
+}
+
+} // namespace ArmISA
+
+ArmISA::FsFreebsd *
+ArmFsFreebsdParams::create()
+{
+ return new ArmISA::FsFreebsd(this);
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * This software was developed by the University of Cambridge Computer
+ * Laboratory as part of the CTSRD Project, with support from the UK Higher
+ * Education Innovation Fund (HEIF).
+ *
+ * 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.
+ */
+
+#ifndef __ARCH_ARM_FREEBSD_FS_WORKLOAD_HH__
+#define __ARCH_ARM_FREEBSD_FS_WORKLOAD_HH__
+
+#include <map>
+
+#include "arch/arm/fs_workload.hh"
+#include "kern/freebsd/events.hh"
+#include "params/ArmFsFreebsd.hh"
+
+namespace ArmISA
+{
+
+class FsFreebsd : public ArmISA::FsWorkload
+{
+ public:
+ /** Boilerplate params code */
+ typedef ArmFsFreebsdParams Params;
+ const Params *
+ params() const
+ {
+ return dynamic_cast<const Params *>(&_params);
+ }
+
+ /** When enabled, dump stats/task info on context switches for
+ * Streamline and per-thread cache occupancy studies, etc. */
+ bool enableContextSwitchStatsDump;
+
+ /** This map stores a mapping of OS process IDs to internal Task IDs. The
+ * mapping is done because the stats system doesn't tend to like vectors
+ * that are much greater than 1000 items and the entire process space is
+ * 65K. */
+ std::map<uint32_t, uint32_t> taskMap;
+
+ /** This is a file that is placed in the run directory that prints out
+ * mappings between taskIds and OS process IDs */
+ std::ostream* taskFile;
+
+ FsFreebsd(Params *p);
+ ~FsFreebsd();
+
+ void initState() override;
+
+ /** This function creates a new task Id for the given pid.
+ * @param tc thread context that is currentyl executing */
+ void mapPid(ThreadContext* tc, uint32_t pid);
+
+ private:
+ /** Event to halt the simulator if the kernel calls panic() */
+ PCEvent *kernelPanicEvent = nullptr;
+
+ /** Event to halt the simulator if the kernel calls oopses */
+ PCEvent *kernelOopsEvent = nullptr;
+
+ /**
+ * PC based event to skip udelay(<time>) calls and quiesce the
+ * processor for the appropriate amount of time. This is not functionally
+ * required but does speed up simulation.
+ */
+ FreeBSD::UDelayEvent *uDelaySkipEvent = nullptr;
+
+ /** These variables store addresses of important data structures
+ * that are normaly kept coherent at boot with cache mainetence operations.
+ * Since these operations aren't supported in gem5, we keep them coherent
+ * by making them uncacheable until all processors in the system boot.
+ */
+ Addr secDataPtrAddr;
+ Addr secDataAddr;
+ Addr penReleaseAddr;
+ Addr pen64ReleaseAddr;
+ Addr bootReleaseAddr;
+};
+
+} // namespace ArmISA
+
+#endif // __ARCH_ARM_FREEBSD_FS_WORKLOAD_HH__
+++ /dev/null
-/*
- * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
- * All rights reserved.
- *
- * This software was developed by the University of Cambridge Computer
- * Laboratory as part of the CTSRD Project, with support from the UK Higher
- * Education Innovation Fund (HEIF).
- *
- * 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.
- */
-
-#include "arch/arm/freebsd/system.hh"
-
-#include "arch/arm/isa_traits.hh"
-#include "arch/arm/utility.hh"
-#include "arch/generic/freebsd/threadinfo.hh"
-#include "base/loader/dtb_file.hh"
-#include "base/loader/object_file.hh"
-#include "base/loader/symtab.hh"
-#include "cpu/base.hh"
-#include "cpu/pc_event.hh"
-#include "cpu/thread_context.hh"
-#include "debug/Loader.hh"
-#include "kern/freebsd/events.hh"
-#include "mem/fs_translating_port_proxy.hh"
-#include "mem/physical.hh"
-#include "sim/stat_control.hh"
-
-using namespace ArmISA;
-using namespace FreeBSD;
-
-FreebsdArmSystem::FreebsdArmSystem(Params *p)
- : GenericArmSystem(p),
- enableContextSwitchStatsDump(p->enable_context_switch_stats_dump),
- taskFile(nullptr), kernelPanicEvent(nullptr), kernelOopsEvent(nullptr)
-{
- if (p->panic_on_panic) {
- kernelPanicEvent = addKernelFuncEventOrPanic<PanicPCEvent>(
- "panic", "Kernel panic in simulated kernel");
- } else {
-#ifndef NDEBUG
- kernelPanicEvent = addKernelFuncEventOrPanic<BreakPCEvent>("panic");
-#endif
- }
-
- if (p->panic_on_oops) {
- kernelOopsEvent = addKernelFuncEventOrPanic<PanicPCEvent>(
- "oops_exit", "Kernel oops in guest");
- }
-
- uDelaySkipEvent = addKernelFuncEvent<UDelayEvent>(
- "DELAY", "DELAY", 1000, 0);
-}
-
-void
-FreebsdArmSystem::initState()
-{
- // Moved from the constructor to here since it relies on the
- // address map being resolved in the interconnect
-
- // Call the initialisation of the super class
- GenericArmSystem::initState();
-
- // Load symbols at physical address, we might not want
- // to do this permanently, for but early bootup work
- // it is helpful.
- if (params()->early_kernel_symbols) {
- kernel->loadGlobalSymbols(kernelSymtab, 0, 0, loadAddrMask);
- kernel->loadGlobalSymbols(debugSymbolTable, 0, 0, loadAddrMask);
- }
-
- // Setup boot data structure
- Addr addr = 0;
-
- // Check if the kernel image has a symbol that tells us it supports
- // device trees.
- bool kernel_has_fdt_support =
- kernelSymtab->findAddress("fdt_get_range", addr);
- bool dtb_file_specified = params()->dtb_filename != "";
-
- if (!dtb_file_specified)
- fatal("dtb file is not specified\n");
-
- if (!kernel_has_fdt_support)
- fatal("kernel must have fdt support\n");
-
- // Kernel supports flattened device tree and dtb file specified.
- // Using Device Tree Blob to describe system configuration.
- inform("Loading DTB file: %s at address %#x\n", params()->dtb_filename,
- params()->atags_addr + loadAddrOffset);
-
- DtbFile *dtb_file = new DtbFile(params()->dtb_filename);
-
- if (!dtb_file->addBootCmdLine(params()->boot_osflags.c_str(),
- params()->boot_osflags.size())) {
- warn("couldn't append bootargs to DTB file: %s\n",
- params()->dtb_filename);
- }
-
- Addr ra = dtb_file->findReleaseAddr();
- if (ra)
- bootReleaseAddr = ra & ~ULL(0x7F);
-
- dtb_file->buildImage().
- offset(params()->atags_addr + loadAddrOffset).write(physProxy);
- delete dtb_file;
-
- // Kernel boot requirements to set up r0, r1 and r2 in ARMv7
- for (int i = 0; i < threadContexts.size(); i++) {
- threadContexts[i]->setIntReg(0, 0);
- threadContexts[i]->setIntReg(1, params()->machine_type);
- threadContexts[i]->setIntReg(2, params()->atags_addr + loadAddrOffset);
- }
-}
-
-FreebsdArmSystem::~FreebsdArmSystem()
-{
- if (uDelaySkipEvent)
- delete uDelaySkipEvent;
- if (constUDelaySkipEvent)
- delete constUDelaySkipEvent;
-}
-
-FreebsdArmSystem *
-FreebsdArmSystemParams::create()
-{
- return new FreebsdArmSystem(this);
-}
+++ /dev/null
-/*
- * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
- * All rights reserved.
- *
- * This software was developed by the University of Cambridge Computer
- * Laboratory as part of the CTSRD Project, with support from the UK Higher
- * Education Innovation Fund (HEIF).
- *
- * 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.
- */
-
-#ifndef __ARCH_ARM_FREEBSD_SYSTEM_HH__
-#define __ARCH_ARM_FREEBSD_SYSTEM_HH__
-
-#include <cstdio>
-#include <map>
-#include <string>
-#include <vector>
-
-#include "arch/arm/system.hh"
-#include "base/output.hh"
-#include "kern/freebsd/events.hh"
-#include "params/FreebsdArmSystem.hh"
-#include "sim/core.hh"
-
-class FreebsdArmSystem : public GenericArmSystem
-{
- public:
- /** Boilerplate params code */
- typedef FreebsdArmSystemParams Params;
- const Params *
- params() const
- {
- return dynamic_cast<const Params *>(_params);
- }
-
- /** When enabled, dump stats/task info on context switches for
- * Streamline and per-thread cache occupancy studies, etc. */
- bool enableContextSwitchStatsDump;
-
- /** This map stores a mapping of OS process IDs to internal Task IDs. The
- * mapping is done because the stats system doesn't tend to like vectors
- * that are much greater than 1000 items and the entire process space is
- * 65K. */
- std::map<uint32_t, uint32_t> taskMap;
-
- /** This is a file that is placed in the run directory that prints out
- * mappings between taskIds and OS process IDs */
- std::ostream* taskFile;
-
- FreebsdArmSystem(Params *p);
- ~FreebsdArmSystem();
-
- void initState();
-
- /** This function creates a new task Id for the given pid.
- * @param tc thread context that is currentyl executing */
- void mapPid(ThreadContext* tc, uint32_t pid);
-
- private:
- /** Event to halt the simulator if the kernel calls panic() */
- PCEvent *kernelPanicEvent;
-
- /** Event to halt the simulator if the kernel calls oopses */
- PCEvent *kernelOopsEvent;
-
- /**
- * PC based event to skip udelay(<time>) calls and quiesce the
- * processor for the appropriate amount of time. This is not functionally
- * required but does speed up simulation.
- */
- FreeBSD::UDelayEvent *uDelaySkipEvent;
-
- /** Another PC based skip event for const_udelay(). Similar to the udelay
- * skip, but this function precomputes the first multiply that is done
- * in the generic case since the parameter is known at compile time.
- * Thus we need to do some division to get back to us.
- */
- FreeBSD::UDelayEvent *constUDelaySkipEvent;
-
- /** These variables store addresses of important data structures
- * that are normaly kept coherent at boot with cache mainetence operations.
- * Since these operations aren't supported in gem5, we keep them coherent
- * by making them uncacheable until all processors in the system boot.
- */
- Addr secDataPtrAddr;
- Addr secDataAddr;
- Addr penReleaseAddr;
- Addr pen64ReleaseAddr;
- Addr bootReleaseAddr;
-};
-
-#endif // __ARCH_ARM_FREEBSD_SYSTEM_HH__
-
--- /dev/null
+/*
+ * Copyright (c) 2010, 2012-2013, 2015,2017-2019 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Copyright (c) 2002-2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "arch/arm/fs_workload.hh"
+
+#include "arch/arm/faults.hh"
+#include "base/loader/object_file.hh"
+#include "base/loader/symtab.hh"
+#include "cpu/thread_context.hh"
+#include "dev/arm/gic_v2.hh"
+#include "kern/system_events.hh"
+#include "params/ArmFsWorkload.hh"
+
+namespace ArmISA
+{
+
+FsWorkload::FsWorkload(Params *p) : OsKernel(*p)
+{
+ bootLoaders.reserve(p->boot_loader.size());
+ for (const auto &bl : p->boot_loader) {
+ std::unique_ptr<ObjectFile> bl_obj;
+ bl_obj.reset(createObjectFile(bl));
+
+ fatal_if(!bl_obj, "Could not read bootloader: %s", bl);
+ bootLoaders.emplace_back(std::move(bl_obj));
+ }
+
+ if (obj) {
+ bootldr = getBootLoader(obj);
+ } else if (!bootLoaders.empty()) {
+ // No kernel specified, default to the first boot loader
+ bootldr = bootLoaders[0].get();
+ }
+
+ fatal_if(!bootLoaders.empty() && !bootldr,
+ "Can't find a matching boot loader / kernel combination!");
+
+ if (bootldr) {
+ bootldr->loadGlobalSymbols(debugSymbolTable);
+
+ entry = bootldr->entryPoint();
+ _highestELIs64 = (bootldr->getArch() == ObjectFile::Arm64);
+ }
+}
+
+void
+FsWorkload::initState()
+{
+ OsKernel::initState();
+
+ // Reset CP15?? What does that mean -- ali
+
+ // FPEXC.EN = 0
+
+ for (auto *tc: system->threadContexts) {
+ Reset().invoke(tc);
+ tc->activate();
+ }
+
+ auto *arm_sys = dynamic_cast<ArmSystem *>(system);
+
+ Addr kernel_entry = (obj->entryPoint() & loadAddrMask) + loadAddrOffset;
+
+ if (bootldr) {
+ bool is_gic_v2 =
+ arm_sys->getGIC()->supportsVersion(BaseGic::GicVersion::GIC_V2);
+ bootldr->buildImage().write(system->physProxy);
+
+ inform("Using bootloader at address %#x", bootldr->entryPoint());
+
+ // Put the address of the boot loader into r7 so we know
+ // where to branch to after the reset fault
+ // All other values needed by the boot loader to know what to do
+ fatal_if(!arm_sys->params()->flags_addr,
+ "flags_addr must be set with bootloader");
+
+ fatal_if(!arm_sys->params()->gic_cpu_addr && is_gic_v2,
+ "gic_cpu_addr must be set with bootloader");
+
+ for (auto tc: arm_sys->threadContexts) {
+ if (!arm_sys->highestELIs64())
+ tc->setIntReg(3, kernel_entry);
+ if (is_gic_v2)
+ tc->setIntReg(4, arm_sys->params()->gic_cpu_addr);
+ tc->setIntReg(5, arm_sys->params()->flags_addr);
+ }
+ inform("Using kernel entry physical address at %#x\n", kernel_entry);
+ } else {
+ // Set the initial PC to be at start of the kernel code
+ if (!arm_sys->highestELIs64())
+ arm_sys->threadContexts[0]->pcState(entry);
+ }
+}
+
+ObjectFile *
+FsWorkload::getBootLoader(ObjectFile *const obj)
+{
+ for (auto &bl : bootLoaders) {
+ if (bl->getArch() == obj->getArch())
+ return bl.get();
+ }
+
+ return nullptr;
+}
+
+} // namespace ArmISA
+
+ArmISA::FsWorkload *
+ArmFsWorkloadParams::create()
+{
+ return new ArmISA::FsWorkload(this);
+}
--- /dev/null
+/*
+ * Copyright (c) 2010, 2012-2013, 2015-2019 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ARCH_ARM_FS_WORKLOAD_HH__
+#define __ARCH_ARM_FS_WORKLOAD_HH__
+
+#include <memory>
+#include <vector>
+
+#include "kern/linux/events.hh"
+#include "params/ArmFsWorkload.hh"
+#include "sim/os_kernel.hh"
+#include "sim/sim_object.hh"
+
+namespace ArmISA
+{
+
+class FsWorkload : public OsKernel
+{
+ protected:
+ /** Bootloaders */
+ std::vector<std::unique_ptr<ObjectFile>> bootLoaders;
+
+ /**
+ * Pointer to the bootloader object
+ */
+ ObjectFile *bootldr = nullptr;
+
+ /**
+ * Whether the highest exception level in software is 64 it.
+ */
+ bool _highestELIs64 = true;
+
+ /**
+ * Get a boot loader that matches the kernel.
+ *
+ * @param obj Kernel binary
+ * @return Pointer to boot loader ObjectFile or nullptr if there
+ * is no matching boot loader.
+ */
+ ObjectFile *getBootLoader(ObjectFile *const obj);
+
+ public:
+ typedef ArmFsWorkloadParams Params;
+ const Params *
+ params() const
+ {
+ return dynamic_cast<const Params *>(&_params);
+ }
+
+ FsWorkload(Params *p);
+
+ void initState() override;
+
+ bool highestELIs64() const { return _highestELIs64; }
+};
+
+} // namespace ArmISA
+
+#endif // __ARCH_ARM_FS_WORKLOAD_HH__
--- /dev/null
+/*
+ * Copyright (c) 2010-2013, 2016 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Copyright (c) 2002-2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "arch/arm/linux/fs_workload.hh"
+
+#include "arch/arm/isa_traits.hh"
+#include "arch/arm/linux/atag.hh"
+#include "arch/arm/system.hh"
+#include "arch/arm/utility.hh"
+#include "arch/generic/linux/threadinfo.hh"
+#include "base/loader/dtb_file.hh"
+#include "base/loader/object_file.hh"
+#include "base/loader/symtab.hh"
+#include "cpu/base.hh"
+#include "cpu/pc_event.hh"
+#include "cpu/thread_context.hh"
+#include "debug/Loader.hh"
+#include "kern/linux/events.hh"
+#include "kern/linux/helpers.hh"
+#include "kern/system_events.hh"
+#include "mem/fs_translating_port_proxy.hh"
+#include "mem/physical.hh"
+#include "sim/stat_control.hh"
+
+using namespace Linux;
+
+namespace ArmISA
+{
+
+FsLinux::FsLinux(Params *p) : ArmISA::FsWorkload(p),
+ enableContextSwitchStatsDump(p->enable_context_switch_stats_dump)
+{}
+
+void
+FsLinux::initState()
+{
+ ArmISA::FsWorkload::initState();
+
+ // Load symbols at physical address, we might not want
+ // to do this permanently, for but early bootup work
+ // it is helpful.
+ if (params()->early_kernel_symbols) {
+ obj->loadGlobalSymbols(symtab, 0, 0, loadAddrMask);
+ obj->loadGlobalSymbols(debugSymbolTable, 0, 0, loadAddrMask);
+ }
+
+ // Setup boot data structure
+ Addr addr;
+ // Check if the kernel image has a symbol that tells us it supports
+ // device trees.
+ bool kernel_has_fdt_support =
+ symtab->findAddress("unflatten_device_tree", addr);
+ bool dtb_file_specified = params()->dtb_filename != "";
+
+ if (kernel_has_fdt_support && dtb_file_specified) {
+ // Kernel supports flattened device tree and dtb file specified.
+ // Using Device Tree Blob to describe system configuration.
+ inform("Loading DTB file: %s at address %#x\n", params()->dtb_filename,
+ params()->atags_addr + loadAddrOffset);
+
+ DtbFile *dtb_file = new DtbFile(params()->dtb_filename);
+
+ if (!dtb_file->addBootCmdLine(
+ commandLine.c_str(), commandLine.size())) {
+ warn("couldn't append bootargs to DTB file: %s\n",
+ params()->dtb_filename);
+ }
+
+ dtb_file->buildImage().
+ offset(params()->atags_addr + loadAddrOffset).
+ write(system->physProxy);
+ delete dtb_file;
+ } else {
+ // Using ATAGS
+ // Warn if the kernel supports FDT and we haven't specified one
+ if (kernel_has_fdt_support) {
+ assert(!dtb_file_specified);
+ warn("Kernel supports device tree, but no DTB file specified\n");
+ }
+ // Warn if the kernel doesn't support FDT and we have specified one
+ if (dtb_file_specified) {
+ assert(!kernel_has_fdt_support);
+ warn("DTB file specified, but no device tree support in kernel\n");
+ }
+
+ AtagCore ac;
+ ac.flags(1); // read-only
+ ac.pagesize(8192);
+ ac.rootdev(0);
+
+ AddrRangeList atagRanges = system->getPhysMem().getConfAddrRanges();
+ fatal_if(atagRanges.size() != 1,
+ "Expected a single ATAG memory entry but got %d",
+ atagRanges.size());
+ AtagMem am;
+ am.memSize(atagRanges.begin()->size());
+ am.memStart(atagRanges.begin()->start());
+
+ AtagCmdline ad;
+ ad.cmdline(commandLine);
+
+ DPRINTF(Loader, "boot command line %d bytes: %s\n",
+ ad.size() << 2, commandLine);
+
+ AtagNone an;
+
+ uint32_t size = ac.size() + am.size() + ad.size() + an.size();
+ uint32_t offset = 0;
+ uint8_t *boot_data = new uint8_t[size << 2];
+
+ offset += ac.copyOut(boot_data + offset);
+ offset += am.copyOut(boot_data + offset);
+ offset += ad.copyOut(boot_data + offset);
+ offset += an.copyOut(boot_data + offset);
+
+ DPRINTF(Loader, "Boot atags was %d bytes in total\n", size << 2);
+ DDUMP(Loader, boot_data, size << 2);
+
+ system->physProxy.writeBlob(params()->atags_addr + loadAddrOffset,
+ boot_data, size << 2);
+
+ delete[] boot_data;
+ }
+
+ // Kernel boot requirements to set up r0, r1 and r2 in ARMv7
+ for (auto tc: system->threadContexts) {
+ tc->setIntReg(0, 0);
+ tc->setIntReg(1, params()->machine_type);
+ tc->setIntReg(2, params()->atags_addr + loadAddrOffset);
+ }
+}
+
+FsLinux::~FsLinux()
+{
+ delete uDelaySkipEvent;
+ delete constUDelaySkipEvent;
+
+ delete dumpStatsPCEvent;
+ delete debugPrintkEvent;
+}
+
+void
+FsLinux::startup()
+{
+ FsWorkload::startup();
+
+ auto *arm_sys = dynamic_cast<ArmSystem *>(system);
+ if (enableContextSwitchStatsDump) {
+ if (!arm_sys->highestELIs64()) {
+ dumpStatsPCEvent =
+ addKernelFuncEvent<DumpStatsPCEvent>("__switch_to");
+ } else {
+ dumpStatsPCEvent =
+ addKernelFuncEvent<DumpStatsPCEvent64>("__switch_to");
+ }
+
+ panic_if(!dumpStatsPCEvent, "dumpStatsPCEvent not created!");
+
+ std::string task_filename = "tasks.txt";
+ taskFile = simout.create(name() + "." + task_filename);
+
+ for (const auto tc : arm_sys->threadContexts) {
+ uint32_t pid = tc->getCpuPtr()->getPid();
+ if (pid != BaseCPU::invldPid) {
+ mapPid(tc, pid);
+ tc->getCpuPtr()->taskId(taskMap[pid]);
+ }
+ }
+ }
+
+ const std::string dmesg_output = name() + ".dmesg";
+ if (params()->panic_on_panic) {
+ kernelPanicEvent = addKernelFuncEventOrPanic<Linux::KernelPanicEvent>(
+ "panic", "Kernel panic in simulated kernel", dmesg_output);
+ } else {
+ kernelPanicEvent = addKernelFuncEventOrPanic<Linux::DmesgDumpEvent>(
+ "panic", "Kernel panic in simulated kernel", dmesg_output);
+ }
+
+ if (params()->panic_on_oops) {
+ kernelOopsEvent = addKernelFuncEventOrPanic<Linux::KernelPanicEvent>(
+ "oops_exit", "Kernel oops in guest", dmesg_output);
+ } else {
+ kernelOopsEvent = addKernelFuncEventOrPanic<Linux::DmesgDumpEvent>(
+ "oops_exit", "Kernel oops in guest", dmesg_output);
+ }
+
+ // With ARM udelay() is #defined to __udelay
+ // newer kernels use __loop_udelay and __loop_const_udelay symbols
+ uDelaySkipEvent = addKernelFuncEvent<UDelayEvent>(
+ "__loop_udelay", "__udelay", 1000, 0);
+ if (!uDelaySkipEvent)
+ uDelaySkipEvent = addKernelFuncEventOrPanic<UDelayEvent>(
+ "__udelay", "__udelay", 1000, 0);
+
+ // constant arguments to udelay() have some precomputation done ahead of
+ // time. Constant comes from code.
+ constUDelaySkipEvent = addKernelFuncEvent<UDelayEvent>(
+ "__loop_const_udelay", "__const_udelay", 1000, 107374);
+ if (!constUDelaySkipEvent)
+ constUDelaySkipEvent = addKernelFuncEventOrPanic<UDelayEvent>(
+ "__const_udelay", "__const_udelay", 1000, 107374);
+
+ debugPrintkEvent = addKernelFuncEvent<DebugPrintkEvent>("dprintk");
+}
+
+void
+FsLinux::mapPid(ThreadContext *tc, uint32_t pid)
+{
+ // Create a new unique identifier for this pid
+ std::map<uint32_t, uint32_t>::iterator itr = taskMap.find(pid);
+ if (itr == taskMap.end()) {
+ uint32_t map_size = taskMap.size();
+ if (map_size > ContextSwitchTaskId::MaxNormalTaskId + 1) {
+ warn_once("Error out of identifiers for cache occupancy stats");
+ taskMap[pid] = ContextSwitchTaskId::Unknown;
+ } else {
+ taskMap[pid] = map_size;
+ }
+ }
+}
+
+void
+FsLinux::dumpDmesg()
+{
+ Linux::dumpDmesg(system->getThreadContext(0), std::cout);
+}
+
+/**
+ * Extracts the information used by the DumpStatsPCEvent by reading the
+ * thread_info pointer passed to __switch_to() in 32 bit ARM Linux
+ *
+ * r0 = task_struct of the previously running process
+ * r1 = thread_info of the previously running process
+ * r2 = thread_info of the next process to run
+ */
+void
+DumpStatsPCEvent::getTaskDetails(ThreadContext *tc, uint32_t &pid,
+ uint32_t &tgid, std::string &next_task_str, int32_t &mm) {
+
+ Linux::ThreadInfo ti(tc);
+ Addr task_descriptor = tc->readIntReg(2);
+ pid = ti.curTaskPID(task_descriptor);
+ tgid = ti.curTaskTGID(task_descriptor);
+ next_task_str = ti.curTaskName(task_descriptor);
+
+ // Streamline treats pid == -1 as the kernel process.
+ // Also pid == 0 implies idle process (except during Linux boot)
+ mm = ti.curTaskMm(task_descriptor);
+}
+
+/**
+ * Extracts the information used by the DumpStatsPCEvent64 by reading the
+ * task_struct pointer passed to __switch_to() in 64 bit ARM Linux
+ *
+ * r0 = task_struct of the previously running process
+ * r1 = task_struct of next process to run
+ */
+void
+DumpStatsPCEvent64::getTaskDetails(ThreadContext *tc, uint32_t &pid,
+ uint32_t &tgid, std::string &next_task_str, int32_t &mm) {
+
+ Linux::ThreadInfo ti(tc);
+ Addr task_struct = tc->readIntReg(1);
+ pid = ti.curTaskPIDFromTaskStruct(task_struct);
+ tgid = ti.curTaskTGIDFromTaskStruct(task_struct);
+ next_task_str = ti.curTaskNameFromTaskStruct(task_struct);
+
+ // Streamline treats pid == -1 as the kernel process.
+ // Also pid == 0 implies idle process (except during Linux boot)
+ mm = ti.curTaskMmFromTaskStruct(task_struct);
+}
+
+/** This function is called whenever the the kernel function
+ * "__switch_to" is called to change running tasks.
+ */
+void
+DumpStatsPCEvent::process(ThreadContext *tc)
+{
+ uint32_t pid = 0;
+ uint32_t tgid = 0;
+ std::string next_task_str;
+ int32_t mm = 0;
+
+ getTaskDetails(tc, pid, tgid, next_task_str, mm);
+
+ bool is_kernel = (mm == 0);
+ if (is_kernel && (pid != 0)) {
+ pid = -1;
+ tgid = -1;
+ next_task_str = "kernel";
+ }
+
+ FsLinux* wl = dynamic_cast<FsLinux *>(tc->getSystemPtr()->workload);
+ panic_if(!wl, "System workload is not ARM Linux!");
+ std::map<uint32_t, uint32_t>& taskMap = wl->taskMap;
+
+ // Create a new unique identifier for this pid
+ wl->mapPid(tc, pid);
+
+ // Set cpu task id, output process info, and dump stats
+ tc->getCpuPtr()->taskId(taskMap[pid]);
+ tc->getCpuPtr()->setPid(pid);
+
+ OutputStream* taskFile = wl->taskFile;
+
+ // Task file is read by cache occupancy plotting script or
+ // Streamline conversion script.
+ ccprintf(*(taskFile->stream()),
+ "tick=%lld %d cpu_id=%d next_pid=%d next_tgid=%d next_task=%s\n",
+ curTick(), taskMap[pid], tc->cpuId(), (int)pid, (int)tgid,
+ next_task_str);
+ taskFile->stream()->flush();
+
+ // Dump and reset statistics
+ Stats::schedStatEvent(true, true, curTick(), 0);
+}
+
+} // namespace ArmISA
+
+FsLinux *
+ArmFsLinuxParams::create()
+{
+ return new FsLinux(this);
+}
--- /dev/null
+/*
+ * Copyright (c) 2010-2013 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ARCH_ARM_LINUX_FS_WORKLOAD_HH__
+#define __ARCH_ARM_LINUX_FS_WORKLOAD_HH__
+
+#include <cstdio>
+#include <map>
+#include <string>
+
+#include "arch/arm/fs_workload.hh"
+#include "base/output.hh"
+#include "kern/linux/events.hh"
+#include "params/ArmFsLinux.hh"
+#include "sim/core.hh"
+
+namespace ArmISA
+{
+
+class DumpStatsPCEvent;
+
+class FsLinux : public ArmISA::FsWorkload
+{
+ protected:
+ /**
+ * PC based event to skip the dprink() call and emulate its
+ * functionality
+ */
+ Linux::DebugPrintkEvent *debugPrintkEvent = nullptr;
+
+ DumpStatsPCEvent *dumpStatsPCEvent = nullptr;
+
+ public:
+ /** Boilerplate params code */
+ typedef ArmFsLinuxParams Params;
+ const Params *
+ params() const
+ {
+ return dynamic_cast<const Params *>(&_params);
+ }
+
+ /** When enabled, dump stats/task info on context switches for
+ * Streamline and per-thread cache occupancy studies, etc. */
+ bool enableContextSwitchStatsDump;
+
+ /** This map stores a mapping of OS process IDs to internal Task IDs. The
+ * mapping is done because the stats system doesn't tend to like vectors
+ * that are much greater than 1000 items and the entire process space is
+ * 65K. */
+ std::map<uint32_t, uint32_t> taskMap;
+
+ /** This is a file that is placed in the run directory that prints out
+ * mappings between taskIds and OS process IDs */
+ OutputStream *taskFile = nullptr;
+
+ FsLinux(Params *p);
+ ~FsLinux();
+
+ void initState() override;
+
+ void startup() override;
+
+ /** This function creates a new task Id for the given pid.
+ * @param tc thread context that is currentyl executing */
+ void mapPid(ThreadContext* tc, uint32_t pid);
+
+ public: // Exported Python methods
+ /**
+ * Dump the kernel's dmesg buffer to stdout
+ */
+ void dumpDmesg();
+
+ private:
+ /** Event to halt the simulator if the kernel calls panic() */
+ PCEvent *kernelPanicEvent = nullptr;
+
+ /** Event to halt the simulator if the kernel calls oopses */
+ PCEvent *kernelOopsEvent = nullptr;
+
+ /**
+ * PC based event to skip udelay(<time>) calls and quiesce the
+ * processor for the appropriate amount of time. This is not functionally
+ * required but does speed up simulation.
+ */
+ Linux::UDelayEvent *uDelaySkipEvent;
+
+ /** Another PC based skip event for const_udelay(). Similar to the udelay
+ * skip, but this function precomputes the first multiply that is done
+ * in the generic case since the parameter is known at compile time.
+ * Thus we need to do some division to get back to us.
+ */
+ Linux::UDelayEvent *constUDelaySkipEvent;
+
+};
+
+class DumpStatsPCEvent : public PCEvent
+{
+ public:
+ DumpStatsPCEvent(PCEventScope *s, const std::string &desc, Addr addr)
+ : PCEvent(s, desc, addr)
+ {}
+
+ void process(ThreadContext* tc) override;
+ protected:
+ virtual void getTaskDetails(ThreadContext *tc, uint32_t &pid,
+ uint32_t &tgid, std::string &next_task_str, int32_t &mm);
+
+};
+
+class DumpStatsPCEvent64 : public DumpStatsPCEvent
+{
+ public:
+ DumpStatsPCEvent64(PCEventScope *s, const std::string &desc, Addr addr)
+ : DumpStatsPCEvent(s, desc, addr)
+ {}
+ private:
+ void getTaskDetails(ThreadContext *tc, uint32_t &pid, uint32_t &tgid,
+ std::string &next_task_str, int32_t &mm) override;
+};
+
+} // namespace ArmISA
+
+#endif // __ARCH_ARM_LINUX_FS_WORKLOAD_HH__
+
+++ /dev/null
-/*
- * Copyright (c) 2010-2013, 2016 ARM Limited
- * All rights reserved
- *
- * The license below extends only to copyright in the software and shall
- * not be construed as granting a license to any other intellectual
- * property including but not limited to intellectual property relating
- * to a hardware implementation of the functionality of the software
- * licensed hereunder. You may use the software subject to the license
- * terms below provided that you ensure that this notice is replicated
- * unmodified and in its entirety in all distributions of the software,
- * modified or unmodified, in source code or in binary form.
- *
- * Copyright (c) 2002-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "arch/arm/linux/system.hh"
-
-#include "arch/arm/isa_traits.hh"
-#include "arch/arm/linux/atag.hh"
-#include "arch/arm/utility.hh"
-#include "arch/generic/linux/threadinfo.hh"
-#include "base/loader/dtb_file.hh"
-#include "base/loader/object_file.hh"
-#include "base/loader/symtab.hh"
-#include "cpu/base.hh"
-#include "cpu/pc_event.hh"
-#include "cpu/thread_context.hh"
-#include "debug/Loader.hh"
-#include "kern/linux/events.hh"
-#include "kern/linux/helpers.hh"
-#include "mem/fs_translating_port_proxy.hh"
-#include "mem/physical.hh"
-#include "sim/stat_control.hh"
-
-using namespace ArmISA;
-using namespace Linux;
-
-LinuxArmSystem::LinuxArmSystem(Params *p)
- : GenericArmSystem(p), dumpStatsPCEvent(nullptr),
- enableContextSwitchStatsDump(p->enable_context_switch_stats_dump),
- taskFile(nullptr), kernelPanicEvent(nullptr), kernelOopsEvent(nullptr)
-{
- const std::string dmesg_output = name() + ".dmesg";
- if (p->panic_on_panic) {
- kernelPanicEvent = addKernelFuncEventOrPanic<Linux::KernelPanicEvent>(
- "panic", "Kernel panic in simulated kernel", dmesg_output);
- } else {
- kernelPanicEvent = addKernelFuncEventOrPanic<Linux::DmesgDumpEvent>(
- "panic", "Kernel panic in simulated kernel", dmesg_output);
- }
-
- if (p->panic_on_oops) {
- kernelOopsEvent = addKernelFuncEventOrPanic<Linux::KernelPanicEvent>(
- "oops_exit", "Kernel oops in guest", dmesg_output);
- } else {
- kernelOopsEvent = addKernelFuncEventOrPanic<Linux::DmesgDumpEvent>(
- "oops_exit", "Kernel oops in guest", dmesg_output);
- }
-
- // With ARM udelay() is #defined to __udelay
- // newer kernels use __loop_udelay and __loop_const_udelay symbols
- uDelaySkipEvent = addKernelFuncEvent<UDelayEvent>(
- "__loop_udelay", "__udelay", 1000, 0);
- if (!uDelaySkipEvent)
- uDelaySkipEvent = addKernelFuncEventOrPanic<UDelayEvent>(
- "__udelay", "__udelay", 1000, 0);
-
- // constant arguments to udelay() have some precomputation done ahead of
- // time. Constant comes from code.
- constUDelaySkipEvent = addKernelFuncEvent<UDelayEvent>(
- "__loop_const_udelay", "__const_udelay", 1000, 107374);
- if (!constUDelaySkipEvent)
- constUDelaySkipEvent = addKernelFuncEventOrPanic<UDelayEvent>(
- "__const_udelay", "__const_udelay", 1000, 107374);
-
-}
-
-void
-LinuxArmSystem::initState()
-{
- // Moved from the constructor to here since it relies on the
- // address map being resolved in the interconnect
-
- // Call the initialisation of the super class
- GenericArmSystem::initState();
-
- // Load symbols at physical address, we might not want
- // to do this permanently, for but early bootup work
- // it is helpful.
- if (params()->early_kernel_symbols) {
- kernel->loadGlobalSymbols(kernelSymtab, 0, 0, loadAddrMask);
- kernel->loadGlobalSymbols(debugSymbolTable, 0, 0, loadAddrMask);
- }
-
- // Setup boot data structure
- Addr addr = 0;
- // Check if the kernel image has a symbol that tells us it supports
- // device trees.
- bool kernel_has_fdt_support =
- kernelSymtab->findAddress("unflatten_device_tree", addr);
- bool dtb_file_specified = params()->dtb_filename != "";
-
- if (kernel_has_fdt_support && dtb_file_specified) {
- // Kernel supports flattened device tree and dtb file specified.
- // Using Device Tree Blob to describe system configuration.
- inform("Loading DTB file: %s at address %#x\n", params()->dtb_filename,
- params()->atags_addr + loadAddrOffset);
-
- DtbFile *dtb_file = new DtbFile(params()->dtb_filename);
-
- if (!dtb_file->addBootCmdLine(params()->boot_osflags.c_str(),
- params()->boot_osflags.size())) {
- warn("couldn't append bootargs to DTB file: %s\n",
- params()->dtb_filename);
- }
-
- dtb_file->buildImage().
- offset(params()->atags_addr + loadAddrOffset).write(physProxy);
- delete dtb_file;
- } else {
- // Using ATAGS
- // Warn if the kernel supports FDT and we haven't specified one
- if (kernel_has_fdt_support) {
- assert(!dtb_file_specified);
- warn("Kernel supports device tree, but no DTB file specified\n");
- }
- // Warn if the kernel doesn't support FDT and we have specified one
- if (dtb_file_specified) {
- assert(!kernel_has_fdt_support);
- warn("DTB file specified, but no device tree support in kernel\n");
- }
-
- AtagCore ac;
- ac.flags(1); // read-only
- ac.pagesize(8192);
- ac.rootdev(0);
-
- AddrRangeList atagRanges = physmem.getConfAddrRanges();
- if (atagRanges.size() != 1) {
- fatal("Expected a single ATAG memory entry but got %d\n",
- atagRanges.size());
- }
- AtagMem am;
- am.memSize(atagRanges.begin()->size());
- am.memStart(atagRanges.begin()->start());
-
- AtagCmdline ad;
- ad.cmdline(params()->boot_osflags);
-
- DPRINTF(Loader, "boot command line %d bytes: %s\n",
- ad.size() <<2, params()->boot_osflags.c_str());
-
- AtagNone an;
-
- uint32_t size = ac.size() + am.size() + ad.size() + an.size();
- uint32_t offset = 0;
- uint8_t *boot_data = new uint8_t[size << 2];
-
- offset += ac.copyOut(boot_data + offset);
- offset += am.copyOut(boot_data + offset);
- offset += ad.copyOut(boot_data + offset);
- offset += an.copyOut(boot_data + offset);
-
- DPRINTF(Loader, "Boot atags was %d bytes in total\n", size << 2);
- DDUMP(Loader, boot_data, size << 2);
-
- physProxy.writeBlob(params()->atags_addr + loadAddrOffset, boot_data,
- size << 2);
-
- delete[] boot_data;
- }
-
- // Kernel boot requirements to set up r0, r1 and r2 in ARMv7
- for (int i = 0; i < threadContexts.size(); i++) {
- threadContexts[i]->setIntReg(0, 0);
- threadContexts[i]->setIntReg(1, params()->machine_type);
- threadContexts[i]->setIntReg(2, params()->atags_addr + loadAddrOffset);
- }
-}
-
-LinuxArmSystem::~LinuxArmSystem()
-{
- if (uDelaySkipEvent)
- delete uDelaySkipEvent;
- if (constUDelaySkipEvent)
- delete constUDelaySkipEvent;
-
- if (dumpStatsPCEvent)
- delete dumpStatsPCEvent;
-}
-
-LinuxArmSystem *
-LinuxArmSystemParams::create()
-{
- return new LinuxArmSystem(this);
-}
-
-void
-LinuxArmSystem::startup()
-{
- GenericArmSystem::startup();
-
- if (enableContextSwitchStatsDump) {
- if (!highestELIs64()) {
- dumpStatsPCEvent =
- addKernelFuncEvent<DumpStatsPCEvent>("__switch_to");
- } else {
- dumpStatsPCEvent =
- addKernelFuncEvent<DumpStatsPCEvent64>("__switch_to");
- }
-
- if (!dumpStatsPCEvent)
- panic("dumpStatsPCEvent not created!");
-
- std::string task_filename = "tasks.txt";
- taskFile = simout.create(name() + "." + task_filename);
-
- for (const auto tc : threadContexts) {
- uint32_t pid = tc->getCpuPtr()->getPid();
- if (pid != BaseCPU::invldPid) {
- mapPid(tc, pid);
- tc->getCpuPtr()->taskId(taskMap[pid]);
- }
- }
- }
-}
-
-void
-LinuxArmSystem::mapPid(ThreadContext *tc, uint32_t pid)
-{
- // Create a new unique identifier for this pid
- std::map<uint32_t, uint32_t>::iterator itr = taskMap.find(pid);
- if (itr == taskMap.end()) {
- uint32_t map_size = taskMap.size();
- if (map_size > ContextSwitchTaskId::MaxNormalTaskId + 1) {
- warn_once("Error out of identifiers for cache occupancy stats");
- taskMap[pid] = ContextSwitchTaskId::Unknown;
- } else {
- taskMap[pid] = map_size;
- }
- }
-}
-
-void
-LinuxArmSystem::dumpDmesg()
-{
- Linux::dumpDmesg(getThreadContext(0), std::cout);
-}
-
-/**
- * Extracts the information used by the DumpStatsPCEvent by reading the
- * thread_info pointer passed to __switch_to() in 32 bit ARM Linux
- *
- * r0 = task_struct of the previously running process
- * r1 = thread_info of the previously running process
- * r2 = thread_info of the next process to run
- */
-void
-DumpStatsPCEvent::getTaskDetails(ThreadContext *tc, uint32_t &pid,
- uint32_t &tgid, std::string &next_task_str, int32_t &mm) {
-
- Linux::ThreadInfo ti(tc);
- Addr task_descriptor = tc->readIntReg(2);
- pid = ti.curTaskPID(task_descriptor);
- tgid = ti.curTaskTGID(task_descriptor);
- next_task_str = ti.curTaskName(task_descriptor);
-
- // Streamline treats pid == -1 as the kernel process.
- // Also pid == 0 implies idle process (except during Linux boot)
- mm = ti.curTaskMm(task_descriptor);
-}
-
-/**
- * Extracts the information used by the DumpStatsPCEvent64 by reading the
- * task_struct pointer passed to __switch_to() in 64 bit ARM Linux
- *
- * r0 = task_struct of the previously running process
- * r1 = task_struct of next process to run
- */
-void
-DumpStatsPCEvent64::getTaskDetails(ThreadContext *tc, uint32_t &pid,
- uint32_t &tgid, std::string &next_task_str, int32_t &mm) {
-
- Linux::ThreadInfo ti(tc);
- Addr task_struct = tc->readIntReg(1);
- pid = ti.curTaskPIDFromTaskStruct(task_struct);
- tgid = ti.curTaskTGIDFromTaskStruct(task_struct);
- next_task_str = ti.curTaskNameFromTaskStruct(task_struct);
-
- // Streamline treats pid == -1 as the kernel process.
- // Also pid == 0 implies idle process (except during Linux boot)
- mm = ti.curTaskMmFromTaskStruct(task_struct);
-}
-
-/** This function is called whenever the the kernel function
- * "__switch_to" is called to change running tasks.
- */
-void
-DumpStatsPCEvent::process(ThreadContext *tc)
-{
- uint32_t pid = 0;
- uint32_t tgid = 0;
- std::string next_task_str;
- int32_t mm = 0;
-
- getTaskDetails(tc, pid, tgid, next_task_str, mm);
-
- bool is_kernel = (mm == 0);
- if (is_kernel && (pid != 0)) {
- pid = -1;
- tgid = -1;
- next_task_str = "kernel";
- }
-
- LinuxArmSystem* sys = dynamic_cast<LinuxArmSystem *>(tc->getSystemPtr());
- if (!sys) {
- panic("System is not LinuxArmSystem while getting Linux process info!");
- }
- std::map<uint32_t, uint32_t>& taskMap = sys->taskMap;
-
- // Create a new unique identifier for this pid
- sys->mapPid(tc, pid);
-
- // Set cpu task id, output process info, and dump stats
- tc->getCpuPtr()->taskId(taskMap[pid]);
- tc->getCpuPtr()->setPid(pid);
-
- OutputStream* taskFile = sys->taskFile;
-
- // Task file is read by cache occupancy plotting script or
- // Streamline conversion script.
- ccprintf(*(taskFile->stream()),
- "tick=%lld %d cpu_id=%d next_pid=%d next_tgid=%d next_task=%s\n",
- curTick(), taskMap[pid], tc->cpuId(), (int) pid, (int) tgid,
- next_task_str);
- taskFile->stream()->flush();
-
- // Dump and reset statistics
- Stats::schedStatEvent(true, true, curTick(), 0);
-}
-
+++ /dev/null
-/*
- * Copyright (c) 2010-2013 ARM Limited
- * All rights reserved
- *
- * The license below extends only to copyright in the software and shall
- * not be construed as granting a license to any other intellectual
- * property including but not limited to intellectual property relating
- * to a hardware implementation of the functionality of the software
- * licensed hereunder. You may use the software subject to the license
- * terms below provided that you ensure that this notice is replicated
- * unmodified and in its entirety in all distributions of the software,
- * modified or unmodified, in source code or in binary form.
- *
- * Copyright (c) 2002-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __ARCH_ARM_LINUX_SYSTEM_HH__
-#define __ARCH_ARM_LINUX_SYSTEM_HH__
-
-#include <cstdio>
-#include <map>
-#include <string>
-#include <vector>
-
-#include "arch/arm/system.hh"
-#include "base/output.hh"
-#include "kern/linux/events.hh"
-#include "params/LinuxArmSystem.hh"
-#include "sim/core.hh"
-
-class DumpStatsPCEvent;
-
-class LinuxArmSystem : public GenericArmSystem
-{
- protected:
- DumpStatsPCEvent *dumpStatsPCEvent;
-
- public:
- /** Boilerplate params code */
- typedef LinuxArmSystemParams Params;
- const Params *
- params() const
- {
- return dynamic_cast<const Params *>(_params);
- }
-
- /** When enabled, dump stats/task info on context switches for
- * Streamline and per-thread cache occupancy studies, etc. */
- bool enableContextSwitchStatsDump;
-
- /** This map stores a mapping of OS process IDs to internal Task IDs. The
- * mapping is done because the stats system doesn't tend to like vectors
- * that are much greater than 1000 items and the entire process space is
- * 65K. */
- std::map<uint32_t, uint32_t> taskMap;
-
- /** This is a file that is placed in the run directory that prints out
- * mappings between taskIds and OS process IDs */
- OutputStream* taskFile;
-
- LinuxArmSystem(Params *p);
- ~LinuxArmSystem();
-
- void initState();
-
- void startup();
-
- /** This function creates a new task Id for the given pid.
- * @param tc thread context that is currentyl executing */
- void mapPid(ThreadContext* tc, uint32_t pid);
-
- public: // Exported Python methods
- /**
- * Dump the kernel's dmesg buffer to stdout
- */
- void dumpDmesg();
-
- private:
- /** Event to halt the simulator if the kernel calls panic() */
- PCEvent *kernelPanicEvent;
-
- /** Event to halt the simulator if the kernel calls oopses */
- PCEvent *kernelOopsEvent;
-
- /**
- * PC based event to skip udelay(<time>) calls and quiesce the
- * processor for the appropriate amount of time. This is not functionally
- * required but does speed up simulation.
- */
- Linux::UDelayEvent *uDelaySkipEvent;
-
- /** Another PC based skip event for const_udelay(). Similar to the udelay
- * skip, but this function precomputes the first multiply that is done
- * in the generic case since the parameter is known at compile time.
- * Thus we need to do some division to get back to us.
- */
- Linux::UDelayEvent *constUDelaySkipEvent;
-
-};
-
-class DumpStatsPCEvent : public PCEvent
-{
- public:
- DumpStatsPCEvent(PCEventScope *s, const std::string &desc, Addr addr)
- : PCEvent(s, desc, addr)
- {}
-
- virtual void process(ThreadContext* tc);
- protected:
- virtual void getTaskDetails(ThreadContext *tc, uint32_t &pid,
- uint32_t &tgid, std::string &next_task_str, int32_t &mm);
-
-};
-
-class DumpStatsPCEvent64 : public DumpStatsPCEvent {
- public:
- DumpStatsPCEvent64(PCEventScope *s, const std::string &desc, Addr addr)
- : DumpStatsPCEvent(s, desc, addr)
- {}
- private:
- void getTaskDetails(ThreadContext *tc, uint32_t &pid, uint32_t &tgid,
- std::string &next_task_str, int32_t &mm) override;
-};
-
-
-#endif // __ARCH_ARM_LINUX_SYSTEM_HH__
-
readSymbol(ThreadContext *tc, const std::string name)
{
PortProxy &vp = tc->getVirtProxy();
- SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
+ SymbolTable *symtab = tc->getSystemPtr()->workload->symtab;
Addr addr;
if (!symtab->findAddress(name, addr))
#include <iostream>
-#include "arch/arm/faults.hh"
+#include "arch/arm/fs_workload.hh"
#include "arch/arm/semihosting.hh"
#include "base/loader/object_file.hh"
#include "base/loader/symtab.hh"
ArmSystem::ArmSystem(Params *p)
: System(p),
- bootLoaders(), bootldr(nullptr),
_haveSecurity(p->have_security),
_haveLPAE(p->have_lpae),
_haveVirtualization(p->have_virtualization),
_haveCrypto(p->have_crypto),
_genericTimer(nullptr),
_gic(nullptr),
- _resetAddr(p->auto_reset_addr ?
- (kernelEntry & loadAddrMask) + loadAddrOffset :
- p->reset_addr),
_highestELIs64(p->highest_el_is_64),
_physAddrRange64(p->phys_addr_range_64),
_haveLargeAsid64(p->have_large_asid_64),
semihosting(p->semihosting),
multiProc(p->multi_proc)
{
- // Check if the physical address range is valid
+ if (p->auto_reset_addr) {
+ _resetAddr = (workload->entry & workload->loadAddrMask) +
+ workload->loadAddrOffset;
+ } else {
+ _resetAddr = p->reset_addr;
+ }
+
+ auto *arm_workload = dynamic_cast<ArmISA::FsWorkload *>(p->workload);
+ panic_if(!arm_workload,
+ "Workload was not the expected type (ArmISA::FsWorkload).");
+
+ warn_if(workload->entry != _resetAddr,
+ "Workload entry point %#x overriding reset address %#x",
+ workload->entry, _resetAddr);
+ _resetAddr = workload->entry;
+
+ if (arm_workload->highestELIs64() != _highestELIs64) {
+ warn("Highest ARM exception-level set to AArch%d but the workload "
+ "is for AArch%d. Assuming you wanted these to match.",
+ _highestELIs64 ? 64 : 32,
+ arm_workload->highestELIs64() ? 64 : 32);
+ _highestELIs64 = arm_workload->highestELIs64();
+ }
+
if (_highestELIs64 && (
_physAddrRange64 < 32 ||
_physAddrRange64 > 48 ||
(_physAddrRange64 % 4 != 0 && _physAddrRange64 != 42))) {
fatal("Invalid physical address range (%d)\n", _physAddrRange64);
}
-
- bootLoaders.reserve(p->boot_loader.size());
- for (const auto &bl : p->boot_loader) {
- std::unique_ptr<ObjectFile> obj;
- obj.reset(createObjectFile(bl));
-
- fatal_if(!obj, "Could not read bootloader: %s\n", bl);
- bootLoaders.emplace_back(std::move(obj));
- }
-
- if (kernel) {
- bootldr = getBootLoader(kernel);
- } else if (!bootLoaders.empty()) {
- // No kernel specified, default to the first boot loader
- bootldr = bootLoaders[0].get();
- }
-
- if (!bootLoaders.empty() && !bootldr)
- fatal("Can't find a matching boot loader / kernel combination!");
-
- if (bootldr) {
- bootldr->loadGlobalSymbols(debugSymbolTable);
-
- warn_if(bootldr->entryPoint() != _resetAddr,
- "Bootloader entry point %#x overriding reset address %#x",
- bootldr->entryPoint(), _resetAddr);
- const_cast<Addr&>(_resetAddr) = bootldr->entryPoint();
-
- if ((bootldr->getArch() == ObjectFile::Arm64) && !_highestELIs64) {
- warn("Highest ARM exception-level set to AArch32 but bootloader "
- "is for AArch64. Assuming you wanted these to match.\n");
- _highestELIs64 = true;
- } else if ((bootldr->getArch() == ObjectFile::Arm) && _highestELIs64) {
- warn("Highest ARM exception-level set to AArch64 but bootloader "
- "is for AArch32. Assuming you wanted these to match.\n");
- _highestELIs64 = false;
- }
- }
-
- debugPrintkEvent = addKernelFuncEvent<DebugPrintkEvent>("dprintk");
-}
-
-void
-ArmSystem::initState()
-{
- // Moved from the constructor to here since it relies on the
- // address map being resolved in the interconnect
-
- // Call the initialisation of the super class
- System::initState();
-
- // Reset CP15?? What does that mean -- ali
-
- // FPEXC.EN = 0
-
- for (auto *tc: threadContexts) {
- Reset().invoke(tc);
- tc->activate();
- }
-
- const Params* p = params();
-
- if (bootldr) {
- bool is_gic_v2 =
- getGIC()->supportsVersion(BaseGic::GicVersion::GIC_V2);
- bootldr->buildImage().write(physProxy);
-
- inform("Using bootloader at address %#x\n", bootldr->entryPoint());
-
- // Put the address of the boot loader into r7 so we know
- // where to branch to after the reset fault
- // All other values needed by the boot loader to know what to do
- if (!p->flags_addr)
- fatal("flags_addr must be set with bootloader\n");
-
- if (!p->gic_cpu_addr && is_gic_v2)
- fatal("gic_cpu_addr must be set with bootloader\n");
-
- for (int i = 0; i < threadContexts.size(); i++) {
- if (!_highestELIs64)
- threadContexts[i]->setIntReg(3, (kernelEntry & loadAddrMask) +
- loadAddrOffset);
- if (is_gic_v2)
- threadContexts[i]->setIntReg(4, params()->gic_cpu_addr);
- threadContexts[i]->setIntReg(5, params()->flags_addr);
- }
- inform("Using kernel entry physical address at %#x\n",
- (kernelEntry & loadAddrMask) + loadAddrOffset);
- } else {
- // Set the initial PC to be at start of the kernel code
- if (!_highestELIs64)
- threadContexts[0]->pcState((kernelEntry & loadAddrMask) +
- loadAddrOffset);
- }
}
bool
return FullSystem? getArmSystem(tc)->haveSecurity() : false;
}
-
-ArmSystem::~ArmSystem()
-{
- if (debugPrintkEvent)
- delete debugPrintkEvent;
-}
-
-ObjectFile *
-ArmSystem::getBootLoader(ObjectFile *const obj)
-{
- for (auto &bl : bootLoaders) {
- if (bl->getArch() == obj->getArch())
- return bl.get();
- }
-
- return nullptr;
-}
-
bool
ArmSystem::haveLPAE(ThreadContext *tc)
{
{
return new ArmSystem(this);
}
-
-void
-GenericArmSystem::initState()
-{
- // Moved from the constructor to here since it relies on the
- // address map being resolved in the interconnect
-
- // Call the initialisation of the super class
- ArmSystem::initState();
-}
-
-GenericArmSystem *
-GenericArmSystemParams::create()
-{
-
- return new GenericArmSystem(this);
-}
#include "kern/linux/events.hh"
#include "params/ArmSystem.hh"
-#include "params/GenericArmSystem.hh"
#include "sim/full_system.hh"
#include "sim/sim_object.hh"
#include "sim/system.hh"
class ArmSystem : public System
{
protected:
- /**
- * PC based event to skip the dprink() call and emulate its
- * functionality
- */
- Linux::DebugPrintkEvent *debugPrintkEvent;
-
- /** Bootloaders */
- std::vector<std::unique_ptr<ObjectFile>> bootLoaders;
-
- /**
- * Pointer to the bootloader object
- */
- ObjectFile *bootldr;
-
/**
* True if this system implements the Security Extensions
*/
/**
* Reset address (ARMv8)
*/
- const Addr _resetAddr;
+ Addr _resetAddr;
/**
* True if the register width of the highest implemented exception level is
*/
ArmSemihosting *const semihosting;
- protected:
- /**
- * Get a boot loader that matches the kernel.
- *
- * @param obj Kernel binary
- * @return Pointer to boot loader ObjectFile or nullptr if there
- * is no matching boot loader.
- */
- ObjectFile *getBootLoader(ObjectFile *const obj);
-
public:
typedef ArmSystemParams Params;
const Params *
}
ArmSystem(Params *p);
- ~ArmSystem();
-
- /**
- * Initialise the system
- */
- virtual void initState();
- virtual Addr fixFuncEventAddr(Addr addr)
+ Addr
+ fixFuncEventAddr(Addr addr) override
{
// Remove the low bit that thumb symbols have set
// but that aren't actually odd aligned
- if (addr & 0x1)
- return addr & ~1;
- return addr;
+ return addr & ~1;
}
/** true if this a multiprocessor system */
bool haveCrypto() const { return _haveCrypto; }
/** Sets the pointer to the Generic Timer. */
- void setGenericTimer(GenericTimer *generic_timer)
+ void
+ setGenericTimer(GenericTimer *generic_timer)
{
_genericTimer = generic_timer;
}
/** Sets the pointer to the GIC. */
- void setGIC(BaseGic *gic)
- {
- _gic = gic;
- }
+ void setGIC(BaseGic *gic) { _gic = gic; }
/** Get a pointer to the system's generic timer model */
GenericTimer *getGenericTimer() const { return _genericTimer; }
bool highestELIs64() const { return _highestELIs64; }
/** Returns the highest implemented exception level */
- ExceptionLevel highestEL() const
+ ExceptionLevel
+ highestEL() const
{
if (_haveSecurity)
return EL3;
/** Returns the reset address if the highest implemented exception level is
* 64 bits (ARMv8) */
Addr resetAddr() const { return _resetAddr; }
+ void setResetAddr(Addr addr) { _resetAddr = addr; }
/** Returns true if ASID is 16 bits in AArch64 (ARMv8) */
bool haveLargeAsid64() const { return _haveLargeAsid64; }
uint8_t physAddrRange64() const { return _physAddrRange64; }
/** Returns the supported physical address range in bits */
- uint8_t physAddrRange() const
+ uint8_t
+ physAddrRange() const
{
if (_highestELIs64)
return _physAddrRange64;
}
/** Returns the physical address mask */
- Addr physAddrMask() const
- {
- return mask(physAddrRange());
- }
+ Addr physAddrMask() const { return mask(physAddrRange()); }
/** Is Arm Semihosting support enabled? */
bool haveSemihosting() const { return semihosting != nullptr; }
uint32_t op, uint32_t param);
};
-class GenericArmSystem : public ArmSystem
-{
- public:
- typedef GenericArmSystemParams Params;
- const Params *
- params() const
- {
- return dynamic_cast<const Params *>(_params);
- }
-
- GenericArmSystem(Params *p) : ArmSystem(p) {};
- virtual ~GenericArmSystem() {};
-
- /**
- * Initialise the system
- */
- virtual void initState();
-};
-
#endif
get_data(const char *symbol, T &data)
{
Addr addr = 0;
- if (!sys->kernelSymtab->findAddress(symbol, addr)) {
+ if (!sys->workload->symtab->findAddress(symbol, addr)) {
warn_once("Unable to find kernel symbol %s\n", symbol);
warn_once("Kernel not compiled with task_struct info; can't get "
"currently executing task/process/thread name/ids!\n");
hex_file_name = Param.String("test.hex","hex file that contains [address,data] pairs")
system_type = Param.UInt64("Type of system we are emulating")
system_rev = Param.UInt64("Revision of system we are emulating")
- load_addr_mask = 0xffffffffff
class LinuxMipsSystem(MipsSystem):
type = 'LinuxMipsSystem'
--- /dev/null
+# -*- mode:python -*-
+
+# Copyright (c) 2016 RISC-V Foundation
+# Copyright (c) 2016 The University of Virginia
+# 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.
+
+from m5.params import *
+
+from m5.objects.System import System
+from m5.objects.OsKernel import OsKernel
+
+class RiscvFsWorkload(OsKernel):
+ type = 'RiscvFsWorkload'
+ cxx_class = 'RiscvISA::FsWorkload'
+ cxx_header = 'arch/riscv/fs_workload.hh'
+ abstract = True
+
+ bare_metal = Param.Bool(False, "Using Bare Metal Application?")
+ reset_vect = Param.Addr(0x0, 'Reset vector')
+
+
+class RiscvBareMetal(RiscvFsWorkload):
+ type = 'RiscvBareMetal'
+ cxx_class = 'RiscvISA::BareMetal'
+ cxx_header = 'arch/riscv/bare_metal/fs_workload.hh'
+ bootloader = Param.String("File, that contains the bootloader code")
+
+ bare_metal = True
class RiscvSystem(System):
type = 'RiscvSystem'
cxx_header = 'arch/riscv/system.hh'
- bare_metal = Param.Bool(False, "Using Bare Metal Application?")
- reset_vect = Param.Addr(0x0, 'Reset vector')
- load_addr_mask = 0xFFFFFFFFFFFFFFFF
-
-
-class BareMetalRiscvSystem(RiscvSystem):
- type = 'BareMetalRiscvSystem'
- cxx_header = 'arch/riscv/bare_metal/system.hh'
- bootloader = Param.String("File, that contains the bootloader code")
-
- bare_metal = True
Source('linux/process.cc')
Source('linux/linux.cc')
- Source('bare_metal/system.cc')
+ Source('bare_metal/fs_workload.cc')
+ SimObject('RiscvFsWorkload.py')
SimObject('RiscvInterrupts.py')
SimObject('RiscvISA.py')
SimObject('RiscvTLB.py')
--- /dev/null
+/*
+ * Copyright (c) 2018 TU Dresden
+ * 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.
+ */
+
+#include "arch/riscv/bare_metal/fs_workload.hh"
+
+#include "base/loader/object_file.hh"
+#include "sim/system.hh"
+
+namespace RiscvISA
+{
+
+BareMetal::BareMetal(Params *p) : RiscvISA::FsWorkload(p),
+ bootloader(createObjectFile(p->bootloader)),
+ bootloaderSymtab(new SymbolTable)
+{
+ fatal_if(!bootloader, "Could not load bootloader file %s.", p->bootloader);
+ _resetVect = bootloader->entryPoint();
+}
+
+BareMetal::~BareMetal()
+{
+ delete bootloader;
+}
+
+void
+BareMetal::initState()
+{
+ RiscvISA::FsWorkload::initState();
+ warn_if(!bootloader->buildImage().write(system->physProxy),
+ "Could not load sections to memory.");
+}
+
+} // namespace RiscvISA
+
+RiscvISA::BareMetal *
+RiscvBareMetalParams::create()
+{
+ return new RiscvISA::BareMetal(this);
+}
--- /dev/null
+/*
+ * Copyright (c) 2018 TU Dresden
+ * 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.
+ */
+
+#ifndef __ARCH_RISCV_BARE_METAL_SYSTEM_HH__
+#define __ARCH_RISCV_BARE_METAL_SYSTEM_HH__
+
+#include "arch/riscv/fs_workload.hh"
+#include "params/RiscvBareMetal.hh"
+
+namespace RiscvISA
+{
+
+class BareMetal : public RiscvISA::FsWorkload
+{
+ protected:
+ ObjectFile *bootloader;
+ SymbolTable *bootloaderSymtab;
+
+ public:
+ typedef RiscvBareMetalParams Params;
+ BareMetal(Params *p);
+ ~BareMetal();
+
+ void initState() override;
+};
+
+} // namespace RiscvISA
+
+#endif // __ARCH_RISCV_BARE_METAL_FS_WORKLOAD_HH__
#include "arch/riscv/faults.hh"
+#include "arch/riscv/fs_workload.hh"
#include "arch/riscv/isa.hh"
#include "arch/riscv/registers.hh"
-#include "arch/riscv/system.hh"
#include "arch/riscv/utility.hh"
#include "cpu/base.hh"
#include "cpu/thread_context.hh"
tc->setMiscReg(MISCREG_MCAUSE, 0);
// Advance the PC to the implementation-defined reset vector
- PCState pc = static_cast<RiscvSystem *>(tc->getSystemPtr())->resetVect();
+ auto workload = dynamic_cast<FsWorkload *>(tc->getSystemPtr()->workload);
+ PCState pc = workload->resetVect();
tc->pcState(pc);
}
--- /dev/null
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * Copyright (c) 2007 MIPS Technologies, Inc.
+ * 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.
+ */
+
+#ifndef __ARCH_RISCV_FS_WORKLOAD_HH__
+#define __ARCH_RISCV_FS_WORKLOAD_HH__
+
+#include "params/RiscvFsWorkload.hh"
+#include "sim/os_kernel.hh"
+#include "sim/sim_object.hh"
+
+namespace RiscvISA
+{
+
+class FsWorkload : public OsKernel
+{
+ protected:
+ // checker for bare metal application
+ bool _isBareMetal;
+ // entry point for simulation
+ Addr _resetVect;
+
+ public:
+ FsWorkload(RiscvFsWorkloadParams *p) : OsKernel(*p),
+ _isBareMetal(p->bare_metal), _resetVect(p->reset_vect)
+ {}
+
+ // return reset vector
+ Addr resetVect() const { return _resetVect; }
+
+ // return bare metal checker
+ bool isBareMetal() const { return _isBareMetal; }
+};
+
+} // namespace RiscvISA
+
+#endif // __ARCH_RISCV_FS_WORKLOAD_HH__
#include "arch/riscv/system.hh"
-#include "arch/vtophys.hh"
-#include "base/loader/object_file.hh"
-#include "base/loader/symtab.hh"
-#include "base/trace.hh"
-#include "mem/physical.hh"
#include "params/RiscvSystem.hh"
-#include "sim/byteswap.hh"
-
-RiscvSystem::RiscvSystem(Params *p)
- : System(p),
- _isBareMetal(p->bare_metal),
- _resetVect(p->reset_vect)
-{
-}
-
-RiscvSystem::~RiscvSystem()
-{
-}
-
-Addr
-RiscvSystem::fixFuncEventAddr(Addr addr)
-{
- return addr;
-}
-
-void
-RiscvSystem::setRiscvAccess(Addr access)
-{}
-
-bool
-RiscvSystem::breakpoint()
-{
- return 0;
-}
RiscvSystem *
RiscvSystemParams::create()
#ifndef __ARCH_RISCV_SYSTEM_HH__
#define __ARCH_RISCV_SYSTEM_HH__
-#include <string>
-#include <vector>
-
-#include "base/loader/symtab.hh"
-#include "cpu/pc_event.hh"
-#include "kern/system_events.hh"
-#include "params/RiscvSystem.hh"
-#include "sim/sim_object.hh"
#include "sim/system.hh"
class RiscvSystem : public System
{
- protected:
- // checker for bare metal application
- bool _isBareMetal;
- // entry point for simulation
- Addr _resetVect;
-
- public:
- typedef RiscvSystemParams Params;
- RiscvSystem(Params *p);
- ~RiscvSystem();
-
- // return reset vector
- Addr resetVect() const { return _resetVect; }
-
- // return bare metal checker
- bool isBareMetal() const { return _isBareMetal; }
-
- virtual bool breakpoint();
-
public:
-
- /**
- * Set the m5RiscvAccess pointer in the console
- */
- void setRiscvAccess(Addr access);
-
- /** console symbol table */
- SymbolTable *consoleSymtab;
-
- /** Object pointer for the console code */
- ObjectFile *console;
-
- protected:
- const Params *params() const { return (const Params *)_params; }
-
- virtual Addr fixFuncEventAddr(Addr addr);
-
+ using System::System;
+ Addr fixFuncEventAddr(Addr addr) override { return addr; }
};
#endif
#include <vector>
#include "arch/riscv/faults.hh"
+#include "arch/riscv/fs_workload.hh"
#include "arch/riscv/pagetable.hh"
#include "arch/riscv/pra_constants.hh"
#include "arch/riscv/system.hh"
* check if we simulate a bare metal system
* if so, we have no tlb, phys addr == virt addr
*/
- if (static_cast<RiscvSystem *>(tc->getSystemPtr())->isBareMetal())
+ auto *workload = dynamic_cast<FsWorkload *>(
+ tc->getSystemPtr()->workload);
+ if (workload->isBareMetal())
req->setFlags(Request::PHYSICAL);
if (req->getFlags() & Request::PHYSICAL) {
* check if we simulate a bare metal system
* if so, we have no tlb, phys addr == virt addr
*/
- if (static_cast<RiscvSystem *>(tc->getSystemPtr())->isBareMetal())
+ auto *workload = dynamic_cast<FsWorkload *>(
+ tc->getSystemPtr()->workload);
+ if (workload->isBareMetal())
req->setFlags(Request::PHYSICAL);
if (req->getFlags() & Request::PHYSICAL) {
Source('asi.cc')
Source('decoder.cc')
Source('faults.cc')
+ Source('fs_workload.cc')
Source('interrupts.cc')
Source('isa.cc')
Source('linux/linux.cc')
Source('utility.cc')
Source('vtophys.cc')
+ SimObject('SparcFsWorkload.py')
SimObject('SparcInterrupts.py')
SimObject('SparcISA.py')
SimObject('SparcNativeTrace.py')
--- /dev/null
+# Copyright (c) 2007 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.
+
+from m5.params import *
+
+from m5.objects.SimpleMemory import SimpleMemory
+from m5.objects.OsKernel import OsKernel
+
+class SparcFsWorkload(OsKernel):
+ type = 'SparcFsWorkload'
+ cxx_header = 'arch/sparc/fs_workload.hh'
+ cxx_class = 'SparcISA::FsWorkload'
+
+ load_addr_mask = 0xffffffffff
+
+ _rom_base = 0xfff0000000
+ _nvram_base = 0x1f11000000
+ _hypervisor_desc_base = 0x1f12080000
+ _partition_desc_base = 0x1f12000000
+
+ reset_addr = Param.Addr(_rom_base, "Address to load ROM at")
+ hypervisor_addr = Param.Addr(Addr('64kB') + _rom_base,
+ "Address to load hypervisor at")
+ openboot_addr = Param.Addr(Addr('512kB') + _rom_base,
+ "Address to load openboot at")
+ nvram_addr = Param.Addr(_nvram_base, "Address to put the nvram")
+ hypervisor_desc_addr = Param.Addr(_hypervisor_desc_base,
+ "Address for the hypervisor description")
+ partition_desc_addr = Param.Addr(_partition_desc_base,
+ "Address for the partition description")
+
+ reset_bin = Param.String("file that contains the reset code")
+ hypervisor_bin = Param.String("file that contains the hypervisor code")
+ openboot_bin = Param.String("file that contains the openboot code")
+ nvram_bin = Param.String("file that contains the contents of nvram")
+ hypervisor_desc_bin = Param.String(
+ "file that contains the hypervisor description")
+ partition_desc_bin = Param.String(
+ "file that contains the partition description")
from m5.params import *
-from m5.objects.SimpleMemory import SimpleMemory
from m5.objects.System import System
class SparcSystem(System):
type = 'SparcSystem'
cxx_header = 'arch/sparc/system.hh'
- _rom_base = 0xfff0000000
- _nvram_base = 0x1f11000000
- _hypervisor_desc_base = 0x1f12080000
- _partition_desc_base = 0x1f12000000
- # ROM for OBP/Reset/Hypervisor
- rom = Param.SimpleMemory(
- SimpleMemory(range=AddrRange(_rom_base, size='8MB')),
- "Memory to hold the ROM data")
- # nvram
- nvram = Param.SimpleMemory(
- SimpleMemory(range=AddrRange(_nvram_base, size='8kB')),
- "Memory to hold the nvram data")
- # hypervisor description
- hypervisor_desc = Param.SimpleMemory(
- SimpleMemory(range=AddrRange(_hypervisor_desc_base, size='8kB')),
- "Memory to hold the hypervisor description")
- # partition description
- partition_desc = Param.SimpleMemory(
- SimpleMemory(range=AddrRange(_partition_desc_base, size='8kB')),
- "Memory to hold the partition description")
-
- reset_addr = Param.Addr(_rom_base, "Address to load ROM at")
- hypervisor_addr = Param.Addr(Addr('64kB') + _rom_base,
- "Address to load hypervisor at")
- openboot_addr = Param.Addr(Addr('512kB') + _rom_base,
- "Address to load openboot at")
- nvram_addr = Param.Addr(_nvram_base, "Address to put the nvram")
- hypervisor_desc_addr = Param.Addr(_hypervisor_desc_base,
- "Address for the hypervisor description")
- partition_desc_addr = Param.Addr(_partition_desc_base,
- "Address for the partition description")
-
- reset_bin = Param.String("file that contains the reset code")
- hypervisor_bin = Param.String("file that contains the hypervisor code")
- openboot_bin = Param.String("file that contains the openboot code")
- nvram_bin = Param.String("file that contains the contents of nvram")
- hypervisor_desc_bin = Param.String("file that contains the hypervisor description")
- partition_desc_bin = Param.String("file that contains the partition description")
- load_addr_mask = 0xffffffffff
--- /dev/null
+/*
+ * Copyright (c) 2002-2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "arch/sparc/fs_workload.hh"
+
+#include "arch/sparc/faults.hh"
+#include "arch/vtophys.hh"
+#include "base/loader/object_file.hh"
+#include "base/loader/symtab.hh"
+#include "base/trace.hh"
+#include "mem/physical.hh"
+#include "params/SparcFsWorkload.hh"
+#include "sim/byteswap.hh"
+#include "sim/system.hh"
+
+namespace
+{
+
+ObjectFile *
+loadFirmwareImage(const std::string &fname, const std::string &name)
+{
+ ObjectFile *obj = createObjectFile(fname, true);
+ fatal_if(!obj, "Could not load %s %s.", name, fname);
+ return obj;
+}
+
+void
+writeFirmwareImage(ObjectFile *obj, Addr addr, const PortProxy &proxy)
+{
+ MemoryImage image = obj->buildImage();
+
+ // If the entry point isn't somewhere in the image, we assume we need to
+ // move where it's loaded so that it is.
+ if (addr < image.minAddr() || addr >= image.maxAddr()) {
+ // Move the image by the difference between the expected entry address,
+ // and the entry point in the object file.
+ image.offset(addr - obj->entryPoint());
+ }
+
+ image.write(proxy);
+}
+
+} // anonymous namespace
+
+namespace SparcISA
+{
+
+FsWorkload::FsWorkload(Params *p) : OsKernel(*p)
+{
+ resetSymtab = new SymbolTable;
+ hypervisorSymtab = new SymbolTable;
+ openbootSymtab = new SymbolTable;
+ nvramSymtab = new SymbolTable;
+ hypervisorDescSymtab = new SymbolTable;
+ partitionDescSymtab = new SymbolTable;
+
+ reset = loadFirmwareImage(params()->reset_bin, "reset binary");
+ openboot = loadFirmwareImage(params()->openboot_bin, "openboot binary");
+ hypervisor = loadFirmwareImage(
+ params()->hypervisor_bin, "hypervisor binary");
+ nvram = loadFirmwareImage(params()->nvram_bin, "nvram image");
+ hypervisor_desc = loadFirmwareImage(
+ params()->hypervisor_desc_bin, "hypervisor description image");
+ partition_desc = loadFirmwareImage(
+ params()->partition_desc_bin, "partition description image");
+
+ // load symbols
+ panic_if(!reset->loadGlobalSymbols(resetSymtab),
+ "could not load reset symbols");
+
+ panic_if(!openboot->loadGlobalSymbols(openbootSymtab),
+ "could not load openboot symbols");
+
+ panic_if(!hypervisor->loadLocalSymbols(hypervisorSymtab),
+ "could not load hypervisor symbols");
+
+ panic_if(!nvram->loadLocalSymbols(nvramSymtab),
+ "could not load nvram symbols");
+
+ panic_if(!hypervisor_desc->loadLocalSymbols(hypervisorDescSymtab),
+ "could not load hypervisor description symbols");
+
+ panic_if(!partition_desc->loadLocalSymbols(partitionDescSymtab),
+ "could not load partition description symbols");
+
+ // load symbols into debug table
+ panic_if(!reset->loadGlobalSymbols(debugSymbolTable),
+ "could not load reset symbols");
+
+ panic_if(!openboot->loadGlobalSymbols(debugSymbolTable),
+ "could not load openboot symbols");
+
+ panic_if(!hypervisor->loadLocalSymbols(debugSymbolTable),
+ "could not load hypervisor symbols");
+
+ // Strip off the rom address so when the hypervisor is copied into memory
+ // we have symbols still
+ panic_if(!hypervisor->loadLocalSymbols(debugSymbolTable, 0, 0, 0xFFFFFF),
+ "could not load hypervisor symbols");
+
+ panic_if(!nvram->loadGlobalSymbols(debugSymbolTable),
+ "could not load reset symbols");
+
+ panic_if(!hypervisor_desc->loadGlobalSymbols(debugSymbolTable),
+ "could not load hypervisor description symbols");
+
+ panic_if(!partition_desc->loadLocalSymbols(debugSymbolTable),
+ "could not load partition description symbols");
+
+}
+
+void
+FsWorkload::initState()
+{
+ OsKernel::initState();
+
+ if (system->threadContexts.empty())
+ return;
+
+ // Other CPUs will get activated by IPIs.
+ auto *tc = system->threadContexts[0];
+ SparcISA::PowerOnReset().invoke(tc);
+ tc->activate();
+
+ auto phys_proxy = system->physProxy;
+
+ writeFirmwareImage(reset, params()->reset_addr, phys_proxy);
+ writeFirmwareImage(openboot, params()->openboot_addr, phys_proxy);
+ writeFirmwareImage(hypervisor, params()->hypervisor_addr, phys_proxy);
+ writeFirmwareImage(nvram, params()->nvram_addr, phys_proxy);
+ writeFirmwareImage(
+ hypervisor_desc, params()->hypervisor_desc_addr, phys_proxy);
+ writeFirmwareImage(
+ partition_desc, params()->partition_desc_addr, phys_proxy);
+}
+
+FsWorkload::~FsWorkload()
+{
+ delete resetSymtab;
+ delete hypervisorSymtab;
+ delete openbootSymtab;
+ delete nvramSymtab;
+ delete hypervisorDescSymtab;
+ delete partitionDescSymtab;
+ delete reset;
+ delete openboot;
+ delete hypervisor;
+ delete nvram;
+ delete hypervisor_desc;
+ delete partition_desc;
+}
+
+void
+FsWorkload::serializeSymtab(CheckpointOut &cp) const
+{
+ resetSymtab->serialize("reset_symtab", cp);
+ hypervisorSymtab->serialize("hypervisor_symtab", cp);
+ openbootSymtab->serialize("openboot_symtab", cp);
+ nvramSymtab->serialize("nvram_symtab", cp);
+ hypervisorDescSymtab->serialize("hypervisor_desc_symtab", cp);
+ partitionDescSymtab->serialize("partition_desc_symtab", cp);
+}
+
+
+void
+FsWorkload::unserializeSymtab(CheckpointIn &cp)
+{
+ resetSymtab->unserialize("reset_symtab", cp);
+ hypervisorSymtab->unserialize("hypervisor_symtab", cp);
+ openbootSymtab->unserialize("openboot_symtab", cp);
+ nvramSymtab->unserialize("nvram_symtab", cp);
+ hypervisorDescSymtab->unserialize("hypervisor_desc_symtab", cp);
+ partitionDescSymtab->unserialize("partition_desc_symtab", cp);
+}
+
+} // namespace SparcISA
+
+SparcISA::FsWorkload *
+SparcFsWorkloadParams::create()
+{
+ return new SparcISA::FsWorkload(this);
+}
--- /dev/null
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ARCH_SPARC_FS_WORKLOAD_HH__
+#define __ARCH_SPARC_FS_WORKLOAD_HH__
+
+#include "base/loader/symtab.hh"
+#include "cpu/pc_event.hh"
+#include "kern/system_events.hh"
+#include "params/SparcFsWorkload.hh"
+#include "sim/os_kernel.hh"
+#include "sim/sim_object.hh"
+
+namespace SparcISA
+{
+
+class FsWorkload : public OsKernel
+{
+ public:
+ typedef SparcFsWorkloadParams Params;
+ FsWorkload(Params *p);
+ ~FsWorkload();
+
+ void initState() override;
+
+/**
+ * Serialization stuff
+ */
+ public:
+ void serializeSymtab(CheckpointOut &cp) const override;
+ void unserializeSymtab(CheckpointIn &cp) override;
+
+ /** reset binary symbol table */
+ SymbolTable *resetSymtab;
+
+ /** hypervison binary symbol table */
+ SymbolTable *hypervisorSymtab;
+
+ /** openboot symbol table */
+ SymbolTable *openbootSymtab;
+
+ /** nvram symbol table? */
+ SymbolTable *nvramSymtab;
+
+ /** hypervisor desc symbol table? */
+ SymbolTable *hypervisorDescSymtab;
+
+ /** partition desc symbol table? */
+ SymbolTable *partitionDescSymtab;
+
+ /** Object pointer for the reset binary */
+ ObjectFile *reset;
+
+ /** Object pointer for the hypervisor code */
+ ObjectFile *hypervisor;
+
+ /** Object pointer for the openboot code */
+ ObjectFile *openboot;
+
+ /** Object pointer for the nvram image */
+ ObjectFile *nvram;
+
+ /** Object pointer for the hypervisor description image */
+ ObjectFile *hypervisor_desc;
+
+ /** Object pointer for the partition description image */
+ ObjectFile *partition_desc;
+
+ protected:
+ const Params *params() const { return (const Params *)&_params; }
+
+ /** Add a function-based event to reset binary. */
+ template <class T>
+ T *
+ addResetFuncEvent(const char *lbl)
+ {
+ return addFuncEvent<T>(resetSymtab, lbl);
+ }
+
+ /** Add a function-based event to the hypervisor. */
+ template <class T>
+ T *
+ addHypervisorFuncEvent(const char *lbl)
+ {
+ return addFuncEvent<T>(hypervisorSymtab, lbl);
+ }
+
+ /** Add a function-based event to the openboot. */
+ template <class T>
+ T *
+ addOpenbootFuncEvent(const char *lbl)
+ {
+ return addFuncEvent<T>(openbootSymtab, lbl);
+ }
+};
+
+} // namespace SparcISA
+
+#endif // __ARCH_SPARC_FS_WORKLOAD_HH__
#include "arch/sparc/system.hh"
-#include "arch/sparc/faults.hh"
-#include "arch/vtophys.hh"
-#include "base/loader/object_file.hh"
-#include "base/loader/symtab.hh"
-#include "base/trace.hh"
-#include "mem/physical.hh"
#include "params/SparcSystem.hh"
-#include "sim/byteswap.hh"
-
-namespace
-{
-
-ObjectFile *
-loadFirmwareImage(const std::string &fname, const std::string &name)
-{
- ObjectFile *obj = createObjectFile(fname, true);
- fatal_if(!obj, "Could not load %s %s.", name, fname);
- return obj;
-}
-
-} // anonymous namespace
-
-SparcSystem::SparcSystem(Params *p)
- : System(p), sysTick(0)
-{
- resetSymtab = new SymbolTable;
- hypervisorSymtab = new SymbolTable;
- openbootSymtab = new SymbolTable;
- nvramSymtab = new SymbolTable;
- hypervisorDescSymtab = new SymbolTable;
- partitionDescSymtab = new SymbolTable;
-
- reset = loadFirmwareImage(params()->reset_bin, "reset binary");
- openboot = loadFirmwareImage(params()->openboot_bin, "openboot binary");
- hypervisor = loadFirmwareImage(
- params()->hypervisor_bin, "hypervisor binary");
- nvram = loadFirmwareImage(params()->nvram_bin, "nvram image");
- hypervisor_desc = loadFirmwareImage(
- params()->hypervisor_desc_bin, "hypervisor description image");
- partition_desc = loadFirmwareImage(
- params()->partition_desc_bin, "partition description image");
-
- // load symbols
- if (!reset->loadGlobalSymbols(resetSymtab))
- panic("could not load reset symbols\n");
-
- if (!openboot->loadGlobalSymbols(openbootSymtab))
- panic("could not load openboot symbols\n");
-
- if (!hypervisor->loadLocalSymbols(hypervisorSymtab))
- panic("could not load hypervisor symbols\n");
-
- if (!nvram->loadLocalSymbols(nvramSymtab))
- panic("could not load nvram symbols\n");
-
- if (!hypervisor_desc->loadLocalSymbols(hypervisorDescSymtab))
- panic("could not load hypervisor description symbols\n");
-
- if (!partition_desc->loadLocalSymbols(partitionDescSymtab))
- panic("could not load partition description symbols\n");
-
- // load symbols into debug table
- if (!reset->loadGlobalSymbols(debugSymbolTable))
- panic("could not load reset symbols\n");
-
- if (!openboot->loadGlobalSymbols(debugSymbolTable))
- panic("could not load openboot symbols\n");
-
- if (!hypervisor->loadLocalSymbols(debugSymbolTable))
- panic("could not load hypervisor symbols\n");
-
- // Strip off the rom address so when the hypervisor is copied into memory we
- // have symbols still
- if (!hypervisor->loadLocalSymbols(debugSymbolTable, 0, 0, 0xFFFFFF))
- panic("could not load hypervisor symbols\n");
-
- if (!nvram->loadGlobalSymbols(debugSymbolTable))
- panic("could not load reset symbols\n");
-
- if (!hypervisor_desc->loadGlobalSymbols(debugSymbolTable))
- panic("could not load hypervisor description symbols\n");
-
- if (!partition_desc->loadLocalSymbols(debugSymbolTable))
- panic("could not load partition description symbols\n");
-
-}
-
-namespace
-{
-
-void
-writeFirmwareImage(ObjectFile *obj, Addr addr, const PortProxy &proxy)
-{
- MemoryImage image = obj->buildImage();
-
- // If the entry point isn't somewhere in the image, we assume we need to
- // move where it's loaded so that it is.
- if (addr < image.minAddr() || addr >= image.maxAddr()) {
- // Move the image by the difference between the expected entry address,
- // and the entry point in the object file.
- image.offset(addr - obj->entryPoint());
- }
-
- image.write(proxy);
-}
-
-} // anonymous namespace
-
-void
-SparcSystem::initState()
-{
- // Call the initialisation of the super class
- System::initState();
-
- writeFirmwareImage(reset, params()->reset_addr, physProxy);
- writeFirmwareImage(openboot, params()->openboot_addr, physProxy);
- writeFirmwareImage(hypervisor, params()->hypervisor_addr, physProxy);
- writeFirmwareImage(nvram, params()->nvram_addr, physProxy);
- writeFirmwareImage(
- hypervisor_desc, params()->hypervisor_desc_addr, physProxy);
- writeFirmwareImage(
- partition_desc, params()->partition_desc_addr, physProxy);
-
- // @todo any fixup code over writing data in binaries on setting break
- // events on functions should happen here.
-
- if (threadContexts.empty())
- return;
-
- // Other CPUs will get activated by IPIs.
- auto *tc = threadContexts[0];
- SparcISA::PowerOnReset().invoke(tc);
- tc->activate();
-}
-
-SparcSystem::~SparcSystem()
-{
- delete resetSymtab;
- delete hypervisorSymtab;
- delete openbootSymtab;
- delete nvramSymtab;
- delete hypervisorDescSymtab;
- delete partitionDescSymtab;
- delete reset;
- delete openboot;
- delete hypervisor;
- delete nvram;
- delete hypervisor_desc;
- delete partition_desc;
-}
-
-void
-SparcSystem::serializeSymtab(CheckpointOut &cp) const
-{
- resetSymtab->serialize("reset_symtab", cp);
- hypervisorSymtab->serialize("hypervisor_symtab", cp);
- openbootSymtab->serialize("openboot_symtab", cp);
- nvramSymtab->serialize("nvram_symtab", cp);
- hypervisorDescSymtab->serialize("hypervisor_desc_symtab", cp);
- partitionDescSymtab->serialize("partition_desc_symtab", cp);
-}
-
-
-void
-SparcSystem::unserializeSymtab(CheckpointIn &cp)
-{
- resetSymtab->unserialize("reset_symtab", cp);
- hypervisorSymtab->unserialize("hypervisor_symtab", cp);
- openbootSymtab->unserialize("openboot_symtab", cp);
- nvramSymtab->unserialize("nvram_symtab", cp);
- hypervisorDescSymtab->unserialize("hypervisor_desc_symtab", cp);
- partitionDescSymtab->unserialize("partition_desc_symtab", cp);
-}
SparcSystem *
SparcSystemParams::create()
#ifndef __ARCH_SPARC_SYSTEM_HH__
#define __ARCH_SPARC_SYSTEM_HH__
-#include <string>
-#include <vector>
-
-#include "base/loader/symtab.hh"
-#include "cpu/pc_event.hh"
-#include "kern/system_events.hh"
-#include "params/SparcSystem.hh"
-#include "sim/sim_object.hh"
#include "sim/system.hh"
class SparcSystem : public System
{
public:
- typedef SparcSystemParams Params;
- SparcSystem(Params *p);
- ~SparcSystem();
-
- void initState() override;
-
-/**
- * Serialization stuff
- */
- public:
- void serializeSymtab(CheckpointOut &cp) const override;
- void unserializeSymtab(CheckpointIn &cp) override;
-
- /** reset binary symbol table */
- SymbolTable *resetSymtab;
-
- /** hypervison binary symbol table */
- SymbolTable *hypervisorSymtab;
-
- /** openboot symbol table */
- SymbolTable *openbootSymtab;
-
- /** nvram symbol table? */
- SymbolTable *nvramSymtab;
-
- /** hypervisor desc symbol table? */
- SymbolTable *hypervisorDescSymtab;
-
- /** partition desc symbol table? */
- SymbolTable *partitionDescSymtab;
-
- /** Object pointer for the reset binary */
- ObjectFile *reset;
-
- /** Object pointer for the hypervisor code */
- ObjectFile *hypervisor;
-
- /** Object pointer for the openboot code */
- ObjectFile *openboot;
-
- /** Object pointer for the nvram image */
- ObjectFile *nvram;
-
- /** Object pointer for the hypervisor description image */
- ObjectFile *hypervisor_desc;
-
- /** Object pointer for the partition description image */
- ObjectFile *partition_desc;
-
- /** System Tick for syncronized tick across all cpus. */
- Tick sysTick;
-
- protected:
- const Params *params() const { return (const Params *)_params; }
-
- /** Add a function-based event to reset binary. */
- template <class T>
- T *
- addResetFuncEvent(const char *lbl)
- {
- return addFuncEvent<T>(resetSymtab, lbl);
- }
-
- /** Add a function-based event to the hypervisor. */
- template <class T>
- T *
- addHypervisorFuncEvent(const char *lbl)
- {
- return addFuncEvent<T>(hypervisorSymtab, lbl);
- }
-
- /** Add a function-based event to the openboot. */
- template <class T>
- T *
- addOpenbootFuncEvent(const char *lbl)
- {
- return addFuncEvent<T>(openbootSymtab, lbl);
- }
+ using System::System;
- Addr
- fixFuncEventAddr(Addr addr) override
- {
- //XXX This may eventually have to do something useful.
- return addr;
- }
+ Addr fixFuncEventAddr(Addr addr) override { return addr; }
};
#endif
Source('decoder_tables.cc')
Source('emulenv.cc')
Source('faults.cc')
+ Source('fs_workload.cc')
Source('insts/badmicroop.cc')
Source('insts/microfpop.cc')
Source('insts/microldstop.cc')
Source('insts/static_inst.cc')
Source('interrupts.cc')
Source('isa.cc')
+ Source('linux/fs_workload.cc')
Source('linux/linux.cc')
Source('linux/process.cc')
- Source('linux/system.cc')
Source('nativetrace.cc')
Source('pagetable.cc')
Source('pagetable_walker.cc')
Source('utility.cc')
Source('vtophys.cc')
+ SimObject('X86FsWorkload.py')
SimObject('X86ISA.py')
SimObject('X86LocalApic.py')
SimObject('X86NativeTrace.py')
--- /dev/null
+# Copyright (c) 2007-2008 The Hewlett-Packard Development Company
+# All rights reserved.
+#
+# The license below extends only to copyright in the software and shall
+# not be construed as granting a license to any other intellectual
+# property including but not limited to intellectual property relating
+# to a hardware implementation of the functionality of the software
+# licensed hereunder. You may use the software subject to the license
+# terms below provided that you ensure that this notice is replicated
+# unmodified and in its entirety in all distributions of the software,
+# modified or unmodified, in source code or in binary form.
+#
+# 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.
+
+from m5.params import *
+
+from m5.objects.E820 import X86E820Table, X86E820Entry
+from m5.objects.SMBios import X86SMBiosSMBiosTable
+from m5.objects.IntelMP import X86IntelMPFloatingPointer, X86IntelMPConfigTable
+from m5.objects.ACPI import X86ACPIRSDP
+from m5.objects.OsKernel import OsKernel
+
+class X86FsWorkload(OsKernel):
+ type = 'X86FsWorkload'
+ cxx_header = 'arch/x86/fs_workload.hh'
+ cxx_class = 'X86ISA::FsWorkload'
+
+ smbios_table = Param.X86SMBiosSMBiosTable(
+ X86SMBiosSMBiosTable(), 'table of smbios/dmi information')
+ intel_mp_pointer = Param.X86IntelMPFloatingPointer(
+ X86IntelMPFloatingPointer(),
+ 'intel mp spec floating pointer structure')
+ intel_mp_table = Param.X86IntelMPConfigTable(
+ X86IntelMPConfigTable(),
+ 'intel mp spec configuration table')
+ acpi_description_table_pointer = Param.X86ACPIRSDP(
+ X86ACPIRSDP(), 'ACPI root description pointer structure')
+
+class X86FsLinux(X86FsWorkload):
+ type = 'X86FsLinux'
+ cxx_header = 'arch/x86/linux/fs_workload.hh'
+ cxx_class = 'X86ISA::FsLinux'
+
+ e820_table = Param.X86E820Table(
+ X86E820Table(), 'E820 map of physical memory')
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-from m5.params import *
-
-from m5.objects.E820 import X86E820Table, X86E820Entry
-from m5.objects.SMBios import X86SMBiosSMBiosTable
-from m5.objects.IntelMP import X86IntelMPFloatingPointer, X86IntelMPConfigTable
-from m5.objects.ACPI import X86ACPIRSDP
from m5.objects.System import System
class X86System(System):
type = 'X86System'
cxx_header = 'arch/x86/system.hh'
- smbios_table = Param.X86SMBiosSMBiosTable(
- X86SMBiosSMBiosTable(), 'table of smbios/dmi information')
- intel_mp_pointer = Param.X86IntelMPFloatingPointer(
- X86IntelMPFloatingPointer(),
- 'intel mp spec floating pointer structure')
- intel_mp_table = Param.X86IntelMPConfigTable(
- X86IntelMPConfigTable(),
- 'intel mp spec configuration table')
- acpi_description_table_pointer = Param.X86ACPIRSDP(
- X86ACPIRSDP(), 'ACPI root description pointer structure')
- load_addr_mask = 0xffffffffffffffff
-
-class LinuxX86System(X86System):
- type = 'LinuxX86System'
- cxx_header = 'arch/x86/linux/system.hh'
-
- e820_table = Param.X86E820Table(
- X86E820Table(), 'E820 map of physical memory')
--- /dev/null
+/*
+ * Copyright (c) 2007 The Hewlett-Packard Development Company
+ * Copyright (c) 2018 TU Dresden
+ * All rights reserved.
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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.
+ */
+
+#include "arch/x86/fs_workload.hh"
+
+#include "arch/x86/bios/intelmp.hh"
+#include "arch/x86/bios/smbios.hh"
+#include "arch/x86/faults.hh"
+#include "arch/x86/isa_traits.hh"
+#include "base/loader/object_file.hh"
+#include "cpu/thread_context.hh"
+#include "params/X86FsWorkload.hh"
+#include "sim/system.hh"
+
+namespace X86ISA
+{
+
+FsWorkload::FsWorkload(Params *p) : OsKernel(*p),
+ smbiosTable(p->smbios_table),
+ mpFloatingPointer(p->intel_mp_pointer),
+ mpConfigTable(p->intel_mp_table),
+ rsdp(p->acpi_description_table_pointer)
+{}
+
+void
+installSegDesc(ThreadContext *tc, SegmentRegIndex seg,
+ SegDescriptor desc, bool longmode)
+{
+ bool honorBase = !longmode || seg == SEGMENT_REG_FS ||
+ seg == SEGMENT_REG_GS ||
+ seg == SEGMENT_REG_TSL ||
+ seg == SYS_SEGMENT_REG_TR;
+
+ SegAttr attr = 0;
+
+ attr.dpl = desc.dpl;
+ attr.unusable = 0;
+ attr.defaultSize = desc.d;
+ attr.longMode = desc.l;
+ attr.avl = desc.avl;
+ attr.granularity = desc.g;
+ attr.present = desc.p;
+ attr.system = desc.s;
+ attr.type = desc.type;
+ if (desc.s) {
+ if (desc.type.codeOrData) {
+ // Code segment
+ attr.expandDown = 0;
+ attr.readable = desc.type.r;
+ attr.writable = 0;
+ } else {
+ // Data segment
+ attr.expandDown = desc.type.e;
+ attr.readable = 1;
+ attr.writable = desc.type.w;
+ }
+ } else {
+ attr.readable = 1;
+ attr.writable = 1;
+ attr.expandDown = 0;
+ }
+
+ tc->setMiscReg(MISCREG_SEG_BASE(seg), desc.base);
+ tc->setMiscReg(MISCREG_SEG_EFF_BASE(seg), honorBase ? desc.base : 0);
+ tc->setMiscReg(MISCREG_SEG_LIMIT(seg), desc.limit);
+ tc->setMiscReg(MISCREG_SEG_ATTR(seg), (RegVal)attr);
+}
+
+void
+FsWorkload::initState()
+{
+ OsKernel::initState();
+
+ for (auto *tc: system->threadContexts) {
+ X86ISA::InitInterrupt(0).invoke(tc);
+
+ if (tc->contextId() == 0) {
+ tc->activate();
+ } else {
+ // This is an application processor (AP). It should be initialized
+ // to look like only the BIOS POST has run on it and put then put
+ // it into a halted state.
+ tc->suspend();
+ }
+ }
+
+ fatal_if(!obj, "No kernel to load.");
+
+ fatal_if(obj->getArch() == ObjectFile::I386,
+ "Loading a 32 bit x86 kernel is not supported.");
+
+ ThreadContext *tc = system->threadContexts[0];
+ auto phys_proxy = system->physProxy;
+
+ // This is the boot strap processor (BSP). Initialize it to look like
+ // the boot loader has just turned control over to the 64 bit OS. We
+ // won't actually set up real mode or legacy protected mode descriptor
+ // tables because we aren't executing any code that would require
+ // them. We do, however toggle the control bits in the correct order
+ // while allowing consistency checks and the underlying mechansims
+ // just to be safe.
+
+ const int NumPDTs = 4;
+
+ const Addr PageMapLevel4 = 0x70000;
+ const Addr PageDirPtrTable = 0x71000;
+ const Addr PageDirTable[NumPDTs] =
+ {0x72000, 0x73000, 0x74000, 0x75000};
+ const Addr GDTBase = 0x76000;
+
+ const int PML4Bits = 9;
+ const int PDPTBits = 9;
+ const int PDTBits = 9;
+
+ /*
+ * Set up the gdt.
+ */
+ uint8_t numGDTEntries = 0;
+ // Place holder at selector 0
+ uint64_t nullDescriptor = 0;
+ phys_proxy.writeBlob(GDTBase + numGDTEntries * 8, &nullDescriptor, 8);
+ numGDTEntries++;
+
+ SegDescriptor initDesc = 0;
+ initDesc.type.codeOrData = 0; // code or data type
+ initDesc.type.c = 0; // conforming
+ initDesc.type.r = 1; // readable
+ initDesc.dpl = 0; // privilege
+ initDesc.p = 1; // present
+ initDesc.l = 1; // longmode - 64 bit
+ initDesc.d = 0; // operand size
+ initDesc.g = 1; // granularity
+ initDesc.s = 1; // system segment
+ initDesc.limit = 0xFFFFFFFF;
+ initDesc.base = 0;
+
+ // 64 bit code segment
+ SegDescriptor csDesc = initDesc;
+ csDesc.type.codeOrData = 1;
+ csDesc.dpl = 0;
+ // Because we're dealing with a pointer and I don't think it's
+ // guaranteed that there isn't anything in a nonvirtual class between
+ // it's beginning in memory and it's actual data, we'll use an
+ // intermediary.
+ uint64_t csDescVal = csDesc;
+ phys_proxy.writeBlob(GDTBase + numGDTEntries * 8, (&csDescVal), 8);
+
+ numGDTEntries++;
+
+ SegSelector cs = 0;
+ cs.si = numGDTEntries - 1;
+
+ tc->setMiscReg(MISCREG_CS, (RegVal)cs);
+
+ // 32 bit data segment
+ SegDescriptor dsDesc = initDesc;
+ uint64_t dsDescVal = dsDesc;
+ phys_proxy.writeBlob(GDTBase + numGDTEntries * 8, (&dsDescVal), 8);
+
+ numGDTEntries++;
+
+ SegSelector ds = 0;
+ ds.si = numGDTEntries - 1;
+
+ tc->setMiscReg(MISCREG_DS, (RegVal)ds);
+ tc->setMiscReg(MISCREG_ES, (RegVal)ds);
+ tc->setMiscReg(MISCREG_FS, (RegVal)ds);
+ tc->setMiscReg(MISCREG_GS, (RegVal)ds);
+ tc->setMiscReg(MISCREG_SS, (RegVal)ds);
+
+ tc->setMiscReg(MISCREG_TSL, 0);
+ tc->setMiscReg(MISCREG_TSG_BASE, GDTBase);
+ tc->setMiscReg(MISCREG_TSG_LIMIT, 8 * numGDTEntries - 1);
+
+ SegDescriptor tssDesc = initDesc;
+ uint64_t tssDescVal = tssDesc;
+ phys_proxy.writeBlob(GDTBase + numGDTEntries * 8, (&tssDescVal), 8);
+
+ numGDTEntries++;
+
+ SegSelector tss = 0;
+ tss.si = numGDTEntries - 1;
+
+ tc->setMiscReg(MISCREG_TR, (RegVal)tss);
+ installSegDesc(tc, SYS_SEGMENT_REG_TR, tssDesc, true);
+
+ /*
+ * Identity map the first 4GB of memory. In order to map this region
+ * of memory in long mode, there needs to be one actual page map level
+ * 4 entry which points to one page directory pointer table which
+ * points to 4 different page directory tables which are full of two
+ * megabyte pages. All of the other entries in valid tables are set
+ * to indicate that they don't pertain to anything valid and will
+ * cause a fault if used.
+ */
+
+ // Put valid values in all of the various table entries which indicate
+ // that those entries don't point to further tables or pages. Then
+ // set the values of those entries which are needed.
+
+ // Page Map Level 4
+
+ // read/write, user, not present
+ uint64_t pml4e = htole<uint64_t>(0x6);
+ for (int offset = 0; offset < (1 << PML4Bits) * 8; offset += 8)
+ phys_proxy.writeBlob(PageMapLevel4 + offset, (&pml4e), 8);
+ // Point to the only PDPT
+ pml4e = htole<uint64_t>(0x7 | PageDirPtrTable);
+ phys_proxy.writeBlob(PageMapLevel4, (&pml4e), 8);
+
+ // Page Directory Pointer Table
+
+ // read/write, user, not present
+ uint64_t pdpe = htole<uint64_t>(0x6);
+ for (int offset = 0; offset < (1 << PDPTBits) * 8; offset += 8)
+ phys_proxy.writeBlob(PageDirPtrTable + offset, &pdpe, 8);
+ // Point to the PDTs
+ for (int table = 0; table < NumPDTs; table++) {
+ pdpe = htole<uint64_t>(0x7 | PageDirTable[table]);
+ phys_proxy.writeBlob(PageDirPtrTable + table * 8, &pdpe, 8);
+ }
+
+ // Page Directory Tables
+
+ Addr base = 0;
+ const Addr pageSize = 2 << 20;
+ for (int table = 0; table < NumPDTs; table++) {
+ for (int offset = 0; offset < (1 << PDTBits) * 8; offset += 8) {
+ // read/write, user, present, 4MB
+ uint64_t pdte = htole(0x87 | base);
+ phys_proxy.writeBlob(PageDirTable[table] + offset, &pdte, 8);
+ base += pageSize;
+ }
+ }
+
+ /*
+ * Transition from real mode all the way up to Long mode
+ */
+ CR0 cr0 = tc->readMiscRegNoEffect(MISCREG_CR0);
+ // Turn off paging.
+ cr0.pg = 0;
+ tc->setMiscReg(MISCREG_CR0, cr0);
+ // Turn on protected mode.
+ cr0.pe = 1;
+ tc->setMiscReg(MISCREG_CR0, cr0);
+
+ CR4 cr4 = tc->readMiscRegNoEffect(MISCREG_CR4);
+ // Turn on pae.
+ cr4.pae = 1;
+ tc->setMiscReg(MISCREG_CR4, cr4);
+
+ // Point to the page tables.
+ tc->setMiscReg(MISCREG_CR3, PageMapLevel4);
+
+ Efer efer = tc->readMiscRegNoEffect(MISCREG_EFER);
+ // Enable long mode.
+ efer.lme = 1;
+ tc->setMiscReg(MISCREG_EFER, efer);
+
+ // Start using longmode segments.
+ installSegDesc(tc, SEGMENT_REG_CS, csDesc, true);
+ installSegDesc(tc, SEGMENT_REG_DS, dsDesc, true);
+ installSegDesc(tc, SEGMENT_REG_ES, dsDesc, true);
+ installSegDesc(tc, SEGMENT_REG_FS, dsDesc, true);
+ installSegDesc(tc, SEGMENT_REG_GS, dsDesc, true);
+ installSegDesc(tc, SEGMENT_REG_SS, dsDesc, true);
+
+ // Activate long mode.
+ cr0.pg = 1;
+ tc->setMiscReg(MISCREG_CR0, cr0);
+
+ tc->pcState(entry);
+
+ // We should now be in long mode. Yay!
+
+ Addr ebdaPos = 0xF0000;
+ Addr fixed, table;
+
+ // Write out the SMBios/DMI table.
+ writeOutSMBiosTable(ebdaPos, fixed, table);
+ ebdaPos += (fixed + table);
+ ebdaPos = roundUp(ebdaPos, 16);
+
+ // Write out the Intel MP Specification configuration table.
+ writeOutMPTable(ebdaPos, fixed, table);
+ ebdaPos += (fixed + table);
+}
+
+void
+FsWorkload::writeOutSMBiosTable(Addr header,
+ Addr &headerSize, Addr &structSize, Addr table)
+{
+ // If the table location isn't specified, just put it after the header.
+ // The header size as of the 2.5 SMBios specification is 0x1F bytes.
+ if (!table)
+ table = header + 0x1F;
+ smbiosTable->setTableAddr(table);
+
+ smbiosTable->writeOut(system->physProxy, header, headerSize, structSize);
+
+ // Do some bounds checking to make sure we at least didn't step on
+ // ourselves.
+ assert(header > table || header + headerSize <= table);
+ assert(table > header || table + structSize <= header);
+}
+
+void
+FsWorkload::writeOutMPTable(Addr fp, Addr &fpSize, Addr &tableSize, Addr table)
+{
+ // If the table location isn't specified and it exists, just put
+ // it after the floating pointer. The fp size as of the 1.4 Intel MP
+ // specification is 0x10 bytes.
+ if (mpConfigTable) {
+ if (!table)
+ table = fp + 0x10;
+ mpFloatingPointer->setTableAddr(table);
+ }
+
+ fpSize = mpFloatingPointer->writeOut(system->physProxy, fp);
+ if (mpConfigTable)
+ tableSize = mpConfigTable->writeOut(system->physProxy, table);
+ else
+ tableSize = 0;
+
+ // Do some bounds checking to make sure we at least didn't step on
+ // ourselves and the fp structure was the size we thought it was.
+ assert(fp > table || fp + fpSize <= table);
+ assert(table > fp || table + tableSize <= fp);
+ assert(fpSize == 0x10);
+}
+
+} // namespace X86ISA
+
+X86ISA::FsWorkload *
+X86FsWorkloadParams::create()
+{
+ return new X86ISA::FsWorkload(this);
+}
--- /dev/null
+/*
+ * Copyright (c) 2007 The Hewlett-Packard Development Company
+ * All rights reserved.
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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.
+ */
+
+#ifndef __ARCH_X86_FS_WORKLOAD_HH__
+#define __ARCH_X86_FS_WORKLOAD_HH__
+
+#include <string>
+#include <vector>
+
+#include "arch/x86/regs/misc.hh"
+#include "arch/x86/regs/segment.hh"
+#include "base/types.hh"
+#include "cpu/thread_context.hh"
+#include "params/X86FsWorkload.hh"
+#include "sim/os_kernel.hh"
+
+namespace X86ISA
+{
+
+namespace SMBios
+{
+
+class SMBiosTable;
+
+} // namespace SMBios
+namespace IntelMP
+{
+
+class FloatingPointer;
+class ConfigTable;
+
+} // namespace IntelMP
+
+/* memory mappings for KVMCpu in SE mode */
+const Addr syscallCodeVirtAddr = 0xffff800000000000;
+const Addr GDTVirtAddr = 0xffff800000001000;
+const Addr IDTVirtAddr = 0xffff800000002000;
+const Addr TSSVirtAddr = 0xffff800000003000;
+const Addr TSSPhysAddr = 0x63000;
+const Addr ISTVirtAddr = 0xffff800000004000;
+const Addr PFHandlerVirtAddr = 0xffff800000005000;
+const Addr MMIORegionVirtAddr = 0xffffc90000000000;
+const Addr MMIORegionPhysAddr = 0xffff0000;
+
+void installSegDesc(ThreadContext *tc, SegmentRegIndex seg,
+ SegDescriptor desc, bool longmode);
+
+class FsWorkload : public OsKernel
+{
+ public:
+ typedef X86FsWorkloadParams Params;
+ FsWorkload(Params *p);
+
+ public:
+ void initState() override;
+
+ protected:
+
+ SMBios::SMBiosTable *smbiosTable;
+ IntelMP::FloatingPointer *mpFloatingPointer;
+ IntelMP::ConfigTable *mpConfigTable;
+ ACPI::RSDP *rsdp;
+
+ void writeOutSMBiosTable(Addr header,
+ Addr &headerSize, Addr &tableSize, Addr table=0);
+
+ void writeOutMPTable(Addr fp,
+ Addr &fpSize, Addr &tableSize, Addr table=0);
+
+ const Params *params() const { return (const Params *)&_params; }
+};
+
+} // namespace X86ISA
+
+#endif // __ARCH_X86_FS_WORKLOAD_HH__
--- /dev/null
+/*
+ * Copyright (c) 2007-2008 The Hewlett-Packard Development Company
+ * All rights reserved.
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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.
+ */
+
+#include "arch/x86/linux/fs_workload.hh"
+
+#include "arch/vtophys.hh"
+#include "arch/x86/isa_traits.hh"
+#include "arch/x86/regs/int.hh"
+#include "base/trace.hh"
+#include "cpu/thread_context.hh"
+#include "mem/port_proxy.hh"
+#include "params/X86FsLinux.hh"
+#include "sim/byteswap.hh"
+#include "sim/system.hh"
+
+namespace X86ISA
+{
+
+FsLinux::FsLinux(Params *p) : X86ISA::FsWorkload(p), e820Table(p->e820_table)
+{}
+
+void
+FsLinux::initState()
+{
+ X86ISA::FsWorkload::initState();
+
+ auto phys_proxy = system->physProxy;
+
+ // The location of the real mode data structure.
+ const Addr realModeData = 0x90200;
+
+ /*
+ * Deal with the command line stuff.
+ */
+
+ // A buffer to store the command line.
+ const Addr commandLineBuff = 0x90000;
+ // A pointer to the commandLineBuff stored in the real mode data.
+ const Addr commandLinePointer = realModeData + 0x228;
+
+ panic_if(commandLine.length() + 1 > realModeData - commandLineBuff,
+ "Command line \"%s\" is longer than %d characters.",
+ commandLine, realModeData - commandLineBuff - 1);
+ phys_proxy.writeString(commandLineBuff, commandLine.c_str());
+
+ // Generate a pointer of the right size and endianness to put into
+ // commandLinePointer.
+ uint32_t guestCommandLineBuff = htole((uint32_t)commandLineBuff);
+ phys_proxy.writeBlob(commandLinePointer, &guestCommandLineBuff,
+ sizeof(guestCommandLineBuff));
+
+ /*
+ * Screen Info.
+ */
+
+ // We'll skip on this for now because it's only needed for framebuffers,
+ // something we don't support at the moment.
+
+ /*
+ * EDID info
+ */
+
+ // Skipping for now.
+
+ /*
+ * Saved video mode
+ */
+
+ // Skipping for now.
+
+ /*
+ * Loader type.
+ */
+
+ // Skipping for now.
+
+ /*
+ * E820 memory map
+ */
+
+ // A pointer to the number of E820 entries there are.
+ const Addr e820MapNrPointer = realModeData + 0x1e8;
+
+ // A pointer to the buffer for E820 entries.
+ const Addr e820MapPointer = realModeData + 0x2d0;
+
+ e820Table->writeTo(phys_proxy, e820MapNrPointer, e820MapPointer);
+
+ /*
+ * Pass the location of the real mode data structure to the kernel
+ * using register %esi. We'll use %rsi which should be equivalent.
+ */
+ system->threadContexts[0]->setIntReg(INTREG_RSI, realModeData);
+}
+
+} // namespace X86ISA
+
+X86ISA::FsLinux *
+X86FsLinuxParams::create()
+{
+ return new X86ISA::FsLinux(this);
+}
--- /dev/null
+/*
+ * Copyright (c) 2007-2008 The Hewlett-Packard Development Company
+ * All rights reserved.
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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.
+ */
+
+#ifndef __ARCH_X86_LINUX_FS_WORKLOAD_HH__
+#define __ARCH_X86_LINUX_FS_WORKLOAD_HH__
+
+#include "arch/x86/bios/e820.hh"
+#include "arch/x86/fs_workload.hh"
+#include "params/X86FsLinux.hh"
+
+namespace X86ISA
+{
+
+class FsLinux : public X86ISA::FsWorkload
+{
+ protected:
+ E820Table *e820Table;
+
+ public:
+ typedef X86FsLinuxParams Params;
+ FsLinux(Params *p);
+
+ void initState() override;
+};
+
+} // namespace X86ISA
+
+#endif // __ARCH_X86_LINUX_FS_WORKLOAD_HH__
+++ /dev/null
-/*
- * Copyright (c) 2007-2008 The Hewlett-Packard Development Company
- * All rights reserved.
- *
- * The license below extends only to copyright in the software and shall
- * not be construed as granting a license to any other intellectual
- * property including but not limited to intellectual property relating
- * to a hardware implementation of the functionality of the software
- * licensed hereunder. You may use the software subject to the license
- * terms below provided that you ensure that this notice is replicated
- * unmodified and in its entirety in all distributions of the software,
- * modified or unmodified, in source code or in binary form.
- *
- * 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.
- */
-
-#include "arch/x86/linux/system.hh"
-
-#include "arch/vtophys.hh"
-#include "arch/x86/isa_traits.hh"
-#include "arch/x86/regs/int.hh"
-#include "base/trace.hh"
-#include "cpu/thread_context.hh"
-#include "mem/port_proxy.hh"
-#include "params/LinuxX86System.hh"
-#include "sim/byteswap.hh"
-
-using namespace X86ISA;
-
-LinuxX86System::LinuxX86System(Params *p)
- : X86System(p), commandLine(p->boot_osflags), e820Table(p->e820_table)
-{
-}
-
-LinuxX86System::~LinuxX86System()
-{
-}
-
-void
-LinuxX86System::initState()
-{
- X86System::initState();
-
- // The location of the real mode data structure.
- const Addr realModeData = 0x90200;
-
- /*
- * Deal with the command line stuff.
- */
-
- // A buffer to store the command line.
- const Addr commandLineBuff = 0x90000;
- // A pointer to the commandLineBuff stored in the real mode data.
- const Addr commandLinePointer = realModeData + 0x228;
-
- if (commandLine.length() + 1 > realModeData - commandLineBuff)
- panic("Command line \"%s\" is longer than %d characters.\n",
- commandLine, realModeData - commandLineBuff - 1);
- physProxy.writeBlob(commandLineBuff, commandLine.c_str(),
- commandLine.length() + 1);
-
- // Generate a pointer of the right size and endianness to put into
- // commandLinePointer.
- uint32_t guestCommandLineBuff = htole((uint32_t)commandLineBuff);
- physProxy.writeBlob(commandLinePointer, &guestCommandLineBuff,
- sizeof(guestCommandLineBuff));
-
- /*
- * Screen Info.
- */
-
- // We'll skip on this for now because it's only needed for framebuffers,
- // something we don't support at the moment.
-
- /*
- * EDID info
- */
-
- // Skipping for now.
-
- /*
- * Saved video mode
- */
-
- // Skipping for now.
-
- /*
- * Loader type.
- */
-
- // Skipping for now.
-
- /*
- * E820 memory map
- */
-
- // A pointer to the number of E820 entries there are.
- const Addr e820MapNrPointer = realModeData + 0x1e8;
-
- // A pointer to the buffer for E820 entries.
- const Addr e820MapPointer = realModeData + 0x2d0;
-
- e820Table->writeTo(physProxy, e820MapNrPointer, e820MapPointer);
-
- /*
- * Pass the location of the real mode data structure to the kernel
- * using register %esi. We'll use %rsi which should be equivalent.
- */
- threadContexts[0]->setIntReg(INTREG_RSI, realModeData);
-}
-
-LinuxX86System *
-LinuxX86SystemParams::create()
-{
- return new LinuxX86System(this);
-}
+++ /dev/null
-/*
- * Copyright (c) 2007-2008 The Hewlett-Packard Development Company
- * All rights reserved.
- *
- * The license below extends only to copyright in the software and shall
- * not be construed as granting a license to any other intellectual
- * property including but not limited to intellectual property relating
- * to a hardware implementation of the functionality of the software
- * licensed hereunder. You may use the software subject to the license
- * terms below provided that you ensure that this notice is replicated
- * unmodified and in its entirety in all distributions of the software,
- * modified or unmodified, in source code or in binary form.
- *
- * 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.
- */
-
-#ifndef __ARCH_LINUX_X86_SYSTEM_HH__
-#define __ARCH_LINUX_X86_SYSTEM_HH__
-
-#include <string>
-#include <vector>
-
-#include "arch/x86/bios/e820.hh"
-#include "arch/x86/system.hh"
-#include "params/LinuxX86System.hh"
-
-class LinuxX86System : public X86System
-{
- protected:
- std::string commandLine;
- X86ISA::E820Table * e820Table;
-
- public:
- typedef LinuxX86SystemParams Params;
- LinuxX86System(Params *p);
- ~LinuxX86System();
-
- void initState();
-};
-
-#endif
-
#include <string>
#include <vector>
+#include "arch/x86/fs_workload.hh"
#include "arch/x86/isa_traits.hh"
#include "arch/x86/regs/misc.hh"
#include "arch/x86/regs/segment.hh"
#include "arch/x86/pseudo_inst.hh"
-#include "arch/x86/system.hh"
+#include "arch/x86/fs_workload.hh"
+#include "arch/x86/isa_traits.hh"
#include "cpu/thread_context.hh"
#include "debug/PseudoInst.hh"
#include "mem/se_translating_port_proxy.hh"
readSymbol(ThreadContext *tc, const std::string name)
{
PortProxy &vp = tc->getVirtProxy();
- SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
+ SymbolTable *symtab = tc->getSystemPtr()->workload->symtab;
Addr addr;
if (!symtab->findAddress(name, addr))
StackTrace::dump()
{
StringWrap name(tc->getCpuPtr()->name());
- SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
+ SymbolTable *symtab = tc->getSystemPtr()->workload->symtab;
DPRINTFN("------ Stack ------\n");
#include "arch/x86/system.hh"
-#include "arch/x86/bios/intelmp.hh"
-#include "arch/x86/bios/smbios.hh"
-#include "arch/x86/faults.hh"
-#include "arch/x86/isa_traits.hh"
-#include "base/loader/object_file.hh"
-#include "cpu/thread_context.hh"
#include "params/X86System.hh"
-using namespace X86ISA;
-
-X86System::X86System(Params *p) :
- System(p), smbiosTable(p->smbios_table),
- mpFloatingPointer(p->intel_mp_pointer),
- mpConfigTable(p->intel_mp_table),
- rsdp(p->acpi_description_table_pointer)
-{
-}
-
-void
-X86ISA::installSegDesc(ThreadContext *tc, SegmentRegIndex seg,
- SegDescriptor desc, bool longmode)
-{
- bool honorBase = !longmode || seg == SEGMENT_REG_FS ||
- seg == SEGMENT_REG_GS ||
- seg == SEGMENT_REG_TSL ||
- seg == SYS_SEGMENT_REG_TR;
-
- SegAttr attr = 0;
-
- attr.dpl = desc.dpl;
- attr.unusable = 0;
- attr.defaultSize = desc.d;
- attr.longMode = desc.l;
- attr.avl = desc.avl;
- attr.granularity = desc.g;
- attr.present = desc.p;
- attr.system = desc.s;
- attr.type = desc.type;
- if (desc.s) {
- if (desc.type.codeOrData) {
- // Code segment
- attr.expandDown = 0;
- attr.readable = desc.type.r;
- attr.writable = 0;
- } else {
- // Data segment
- attr.expandDown = desc.type.e;
- attr.readable = 1;
- attr.writable = desc.type.w;
- }
- } else {
- attr.readable = 1;
- attr.writable = 1;
- attr.expandDown = 0;
- }
-
- tc->setMiscReg(MISCREG_SEG_BASE(seg), desc.base);
- tc->setMiscReg(MISCREG_SEG_EFF_BASE(seg), honorBase ? desc.base : 0);
- tc->setMiscReg(MISCREG_SEG_LIMIT(seg), desc.limit);
- tc->setMiscReg(MISCREG_SEG_ATTR(seg), (RegVal)attr);
-}
-
-void
-X86System::initState()
-{
- System::initState();
-
- for (auto *tc: threadContexts) {
- X86ISA::InitInterrupt(0).invoke(tc);
-
- if (tc->contextId() == 0) {
- tc->activate();
- } else {
- // This is an application processor (AP). It should be initialized
- // to look like only the BIOS POST has run on it and put then put
- // it into a halted state.
- tc->suspend();
- }
- }
-
- if (!kernel)
- fatal("No kernel to load.\n");
-
- if (kernel->getArch() == ObjectFile::I386)
- fatal("Loading a 32 bit x86 kernel is not supported.\n");
-
- ThreadContext *tc = threadContexts[0];
- // This is the boot strap processor (BSP). Initialize it to look like
- // the boot loader has just turned control over to the 64 bit OS. We
- // won't actually set up real mode or legacy protected mode descriptor
- // tables because we aren't executing any code that would require
- // them. We do, however toggle the control bits in the correct order
- // while allowing consistency checks and the underlying mechansims
- // just to be safe.
-
- const int NumPDTs = 4;
-
- const Addr PageMapLevel4 = 0x70000;
- const Addr PageDirPtrTable = 0x71000;
- const Addr PageDirTable[NumPDTs] =
- {0x72000, 0x73000, 0x74000, 0x75000};
- const Addr GDTBase = 0x76000;
-
- const int PML4Bits = 9;
- const int PDPTBits = 9;
- const int PDTBits = 9;
-
- /*
- * Set up the gdt.
- */
- uint8_t numGDTEntries = 0;
- // Place holder at selector 0
- uint64_t nullDescriptor = 0;
- physProxy.writeBlob(GDTBase + numGDTEntries * 8, &nullDescriptor, 8);
- numGDTEntries++;
-
- SegDescriptor initDesc = 0;
- initDesc.type.codeOrData = 0; // code or data type
- initDesc.type.c = 0; // conforming
- initDesc.type.r = 1; // readable
- initDesc.dpl = 0; // privilege
- initDesc.p = 1; // present
- initDesc.l = 1; // longmode - 64 bit
- initDesc.d = 0; // operand size
- initDesc.g = 1; // granularity
- initDesc.s = 1; // system segment
- initDesc.limit = 0xFFFFFFFF;
- initDesc.base = 0;
-
- // 64 bit code segment
- SegDescriptor csDesc = initDesc;
- csDesc.type.codeOrData = 1;
- csDesc.dpl = 0;
- // Because we're dealing with a pointer and I don't think it's
- // guaranteed that there isn't anything in a nonvirtual class between
- // it's beginning in memory and it's actual data, we'll use an
- // intermediary.
- uint64_t csDescVal = csDesc;
- physProxy.writeBlob(GDTBase + numGDTEntries * 8, (&csDescVal), 8);
-
- numGDTEntries++;
-
- SegSelector cs = 0;
- cs.si = numGDTEntries - 1;
-
- tc->setMiscReg(MISCREG_CS, (RegVal)cs);
-
- // 32 bit data segment
- SegDescriptor dsDesc = initDesc;
- uint64_t dsDescVal = dsDesc;
- physProxy.writeBlob(GDTBase + numGDTEntries * 8, (&dsDescVal), 8);
-
- numGDTEntries++;
-
- SegSelector ds = 0;
- ds.si = numGDTEntries - 1;
-
- tc->setMiscReg(MISCREG_DS, (RegVal)ds);
- tc->setMiscReg(MISCREG_ES, (RegVal)ds);
- tc->setMiscReg(MISCREG_FS, (RegVal)ds);
- tc->setMiscReg(MISCREG_GS, (RegVal)ds);
- tc->setMiscReg(MISCREG_SS, (RegVal)ds);
-
- tc->setMiscReg(MISCREG_TSL, 0);
- tc->setMiscReg(MISCREG_TSG_BASE, GDTBase);
- tc->setMiscReg(MISCREG_TSG_LIMIT, 8 * numGDTEntries - 1);
-
- SegDescriptor tssDesc = initDesc;
- uint64_t tssDescVal = tssDesc;
- physProxy.writeBlob(GDTBase + numGDTEntries * 8, (&tssDescVal), 8);
-
- numGDTEntries++;
-
- SegSelector tss = 0;
- tss.si = numGDTEntries - 1;
-
- tc->setMiscReg(MISCREG_TR, (RegVal)tss);
- installSegDesc(tc, SYS_SEGMENT_REG_TR, tssDesc, true);
-
- /*
- * Identity map the first 4GB of memory. In order to map this region
- * of memory in long mode, there needs to be one actual page map level
- * 4 entry which points to one page directory pointer table which
- * points to 4 different page directory tables which are full of two
- * megabyte pages. All of the other entries in valid tables are set
- * to indicate that they don't pertain to anything valid and will
- * cause a fault if used.
- */
-
- // Put valid values in all of the various table entries which indicate
- // that those entries don't point to further tables or pages. Then
- // set the values of those entries which are needed.
-
- // Page Map Level 4
-
- // read/write, user, not present
- uint64_t pml4e = htole<uint64_t>(0x6);
- for (int offset = 0; offset < (1 << PML4Bits) * 8; offset += 8) {
- physProxy.writeBlob(PageMapLevel4 + offset, (&pml4e), 8);
- }
- // Point to the only PDPT
- pml4e = htole<uint64_t>(0x7 | PageDirPtrTable);
- physProxy.writeBlob(PageMapLevel4, (&pml4e), 8);
-
- // Page Directory Pointer Table
-
- // read/write, user, not present
- uint64_t pdpe = htole<uint64_t>(0x6);
- for (int offset = 0; offset < (1 << PDPTBits) * 8; offset += 8)
- physProxy.writeBlob(PageDirPtrTable + offset, &pdpe, 8);
- // Point to the PDTs
- for (int table = 0; table < NumPDTs; table++) {
- pdpe = htole<uint64_t>(0x7 | PageDirTable[table]);
- physProxy.writeBlob(PageDirPtrTable + table * 8, &pdpe, 8);
- }
-
- // Page Directory Tables
-
- Addr base = 0;
- const Addr pageSize = 2 << 20;
- for (int table = 0; table < NumPDTs; table++) {
- for (int offset = 0; offset < (1 << PDTBits) * 8; offset += 8) {
- // read/write, user, present, 4MB
- uint64_t pdte = htole(0x87 | base);
- physProxy.writeBlob(PageDirTable[table] + offset, &pdte, 8);
- base += pageSize;
- }
- }
-
- /*
- * Transition from real mode all the way up to Long mode
- */
- CR0 cr0 = tc->readMiscRegNoEffect(MISCREG_CR0);
- // Turn off paging.
- cr0.pg = 0;
- tc->setMiscReg(MISCREG_CR0, cr0);
- // Turn on protected mode.
- cr0.pe = 1;
- tc->setMiscReg(MISCREG_CR0, cr0);
-
- CR4 cr4 = tc->readMiscRegNoEffect(MISCREG_CR4);
- // Turn on pae.
- cr4.pae = 1;
- tc->setMiscReg(MISCREG_CR4, cr4);
-
- // Point to the page tables.
- tc->setMiscReg(MISCREG_CR3, PageMapLevel4);
-
- Efer efer = tc->readMiscRegNoEffect(MISCREG_EFER);
- // Enable long mode.
- efer.lme = 1;
- tc->setMiscReg(MISCREG_EFER, efer);
-
- // Start using longmode segments.
- installSegDesc(tc, SEGMENT_REG_CS, csDesc, true);
- installSegDesc(tc, SEGMENT_REG_DS, dsDesc, true);
- installSegDesc(tc, SEGMENT_REG_ES, dsDesc, true);
- installSegDesc(tc, SEGMENT_REG_FS, dsDesc, true);
- installSegDesc(tc, SEGMENT_REG_GS, dsDesc, true);
- installSegDesc(tc, SEGMENT_REG_SS, dsDesc, true);
-
- // Activate long mode.
- cr0.pg = 1;
- tc->setMiscReg(MISCREG_CR0, cr0);
-
- tc->pcState(tc->getSystemPtr()->kernelEntry);
-
- // We should now be in long mode. Yay!
-
- Addr ebdaPos = 0xF0000;
- Addr fixed, table;
-
- // Write out the SMBios/DMI table.
- writeOutSMBiosTable(ebdaPos, fixed, table);
- ebdaPos += (fixed + table);
- ebdaPos = roundUp(ebdaPos, 16);
-
- // Write out the Intel MP Specification configuration table.
- writeOutMPTable(ebdaPos, fixed, table);
- ebdaPos += (fixed + table);
-}
-
-void
-X86System::writeOutSMBiosTable(Addr header,
- Addr &headerSize, Addr &structSize, Addr table)
-{
- // If the table location isn't specified, just put it after the header.
- // The header size as of the 2.5 SMBios specification is 0x1F bytes.
- if (!table)
- table = header + 0x1F;
- smbiosTable->setTableAddr(table);
-
- smbiosTable->writeOut(physProxy, header, headerSize, structSize);
-
- // Do some bounds checking to make sure we at least didn't step on
- // ourselves.
- assert(header > table || header + headerSize <= table);
- assert(table > header || table + structSize <= header);
-}
-
-void
-X86System::writeOutMPTable(Addr fp,
- Addr &fpSize, Addr &tableSize, Addr table)
-{
- // If the table location isn't specified and it exists, just put
- // it after the floating pointer. The fp size as of the 1.4 Intel MP
- // specification is 0x10 bytes.
- if (mpConfigTable) {
- if (!table)
- table = fp + 0x10;
- mpFloatingPointer->setTableAddr(table);
- }
-
- fpSize = mpFloatingPointer->writeOut(physProxy, fp);
- if (mpConfigTable)
- tableSize = mpConfigTable->writeOut(physProxy, table);
- else
- tableSize = 0;
-
- // Do some bounds checking to make sure we at least didn't step on
- // ourselves and the fp structure was the size we thought it was.
- assert(fp > table || fp + fpSize <= table);
- assert(table > fp || table + tableSize <= fp);
- assert(fpSize == 0x10);
-}
-
-
-X86System::~X86System()
-{
- delete smbiosTable;
-}
-
X86System *
X86SystemParams::create()
{
#ifndef __ARCH_X86_SYSTEM_HH__
#define __ARCH_X86_SYSTEM_HH__
-#include <string>
-#include <vector>
-
-#include "arch/x86/regs/misc.hh"
#include "params/X86System.hh"
#include "sim/system.hh"
-namespace X86ISA
-{
- namespace SMBios
- {
- class SMBiosTable;
- }
- namespace IntelMP
- {
- class FloatingPointer;
- class ConfigTable;
- }
-
- void installSegDesc(ThreadContext *tc, SegmentRegIndex seg,
- SegDescriptor desc, bool longmode);
-
- /* memory mappings for KVMCpu in SE mode */
- const uint64_t syscallCodeVirtAddr = 0xffff800000000000;
- const uint64_t GDTVirtAddr = 0xffff800000001000;
- const uint64_t IDTVirtAddr = 0xffff800000002000;
- const uint64_t TSSVirtAddr = 0xffff800000003000;
- const uint64_t TSSPhysAddr = 0x63000;
- const uint64_t ISTVirtAddr = 0xffff800000004000;
- const uint64_t PFHandlerVirtAddr = 0xffff800000005000;
- const uint64_t MMIORegionVirtAddr = 0xffffc90000000000;
- const uint64_t MMIORegionPhysAddr = 0xffff0000;
-}
-
class X86System : public System
{
public:
- typedef X86SystemParams Params;
- X86System(Params *p);
- ~X86System();
-
-/**
- * Serialization stuff
- */
- public:
-
- void initState();
-
- protected:
-
- X86ISA::SMBios::SMBiosTable * smbiosTable;
- X86ISA::IntelMP::FloatingPointer * mpFloatingPointer;
- X86ISA::IntelMP::ConfigTable * mpConfigTable;
- X86ISA::ACPI::RSDP * rsdp;
-
- void writeOutSMBiosTable(Addr header,
- Addr &headerSize, Addr &tableSize, Addr table = 0);
-
- void writeOutMPTable(Addr fp,
- Addr &fpSize, Addr &tableSize, Addr table = 0);
-
- const Params *params() const { return (const Params *)_params; }
-
- virtual Addr fixFuncEventAddr(Addr addr)
- {
- // XXX This may eventually have to do something useful.
- return addr;
- }
+ using System::System;
+ Addr fixFuncEventAddr(Addr addr) override { return addr; }
};
-#endif
-
+#endif // __ARCH_X86_SYSTEM_HH__
if (cpu->params()->profile) {
profile = new FunctionProfile(
- cpu->params()->system->kernelSymtab);
+ cpu->params()->system->workload->symtab);
Callback *cb =
new MakeCallback<O3ThreadState,
&O3ThreadState::dumpFuncProfile>(this);
clearArchRegs();
if (baseCpu->params()->profile) {
- profile = new FunctionProfile(system->kernelSymtab);
+ profile = new FunctionProfile(system->workload->symtab);
Callback *cb =
new MakeCallback<SimpleThread,
&SimpleThread::dumpFuncProfile>(this);
self._attach_io(self._off_chip_devices(), *args, **kwargs)
def setupBootLoader(self, cur_sys, boot_loader, atags_addr, load_offset):
- cur_sys.boot_loader = boot_loader
- cur_sys.atags_addr = atags_addr
- cur_sys.load_offset = load_offset
+ cur_sys.workload.boot_loader = boot_loader
+ cur_sys.workload.atags_addr = atags_addr
+ cur_sys.workload.load_addr_offset = load_offset
def generateDeviceTree(self, state):
node = FdtNode("/") # Things in this module need to end up in the root
{
System *system = tc->getSystemPtr();
const ByteOrder bo = system->getGuestByteOrder();
- const SymbolTable *symtab = system->kernelSymtab;
+ const SymbolTable *symtab = system->workload->symtab;
PortProxy &proxy = tc->getVirtProxy();
Addr addr_lb = 0, addr_lb_len = 0, addr_first = 0, addr_next = 0;
--- /dev/null
+# Copyright 2019 Google Inc.
+#
+# 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.
+
+from m5.params import *
+from m5.SimObject import SimObject
+
+from m5.objects.SimpleMemory import *
+
+class OsKernel(SimObject):
+ type = 'OsKernel'
+ cxx_header = "sim/os_kernel.hh"
+
+ object_file = Param.String("", "File that contains the kernel code")
+ extras = VectorParam.String([], "Additional object files to load")
+ extras_addrs = VectorParam.Addr([],
+ "Load addresses for additional object files")
+
+ addr_check = Param.Bool(True,
+ "whether to bounds check kernel addresses (disable for baremetal)")
+ load_addr_mask = Param.UInt64(0xffffffffffffffff,
+ "Mask to apply to kernel addresses. If zero, "
+ "auto-calculated to be the most restrictive.")
+ load_addr_offset = Param.UInt64(0, "Address to offset the kernel with")
+
+ command_line = Param.String("a", "boot flags to pass to the kernel")
SimObject('ClockedObject.py')
SimObject('TickedObject.py')
+SimObject('OsKernel.py')
SimObject('Root.py')
SimObject('ClockDomain.py')
SimObject('VoltageDomain.py')
Source('init.cc', add_tags='python')
Source('init_signals.cc')
Source('main.cc', tags='main')
+Source('os_kernel.cc')
Source('port.cc')
Source('python.cc', add_tags='python')
Source('redirect_path.cc')
work_cpus_ckpt_count = Param.Counter(0,
"create checkpoint when active cpu count value is reached")
+ workload = Param.OsKernel(NULL, "Operating system kernel")
init_param = Param.UInt64(0, "numerical value to pass into simulator")
- boot_osflags = Param.String("a", "boot flags to pass to the kernel")
- kernel = Param.String("", "file that contains the kernel code")
- kernel_addr_check = Param.Bool(True,
- "whether to address check on kernel (disable for baremetal)")
- kernel_extras = VectorParam.String([], "Additional object files to load")
- kernel_extras_addrs = VectorParam.Addr([],
- "Load addresses for additional object files")
readfile = Param.String("", "file to read startup script from")
symbolfile = Param.String("", "file to get the symbols from")
- load_addr_mask = Param.UInt64(0xffffffffffffffff,
- "Address to mask loading binaries with, if 0, system "
- "auto-calculates the mask to be the most restrictive, "
- "otherwise it obeys a custom mask.")
- load_offset = Param.UInt64(0, "Address to offset loading binaries with")
multi_thread = Param.Bool(False,
"Supports multi-threaded CPUs? Impacts Thread/Context IDs")
--- /dev/null
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * 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.
+ */
+
+#include "sim/os_kernel.hh"
+
+#include "base/loader/object_file.hh"
+#include "base/loader/symtab.hh"
+#include "debug/Loader.hh"
+#include "params/OsKernel.hh"
+#include "sim/system.hh"
+
+OsKernel::OsKernel(const Params &p) : SimObject(&p), _params(p),
+ commandLine(p.command_line), symtab(new SymbolTable),
+ loadAddrMask(p.load_addr_mask), loadAddrOffset(p.load_addr_offset)
+{
+ if (!debugSymbolTable)
+ debugSymbolTable = new SymbolTable;
+
+ if (params().object_file == "") {
+ inform("No kernel set for full system simulation. "
+ "Assuming you know what you're doing.");
+ } else {
+ obj = createObjectFile(params().object_file);
+ inform("kernel located at: %s", params().object_file);
+
+ fatal_if(!obj, "Could not load kernel file %s", params().object_file);
+
+ image = obj->buildImage();
+
+ start = image.minAddr();
+ end = image.maxAddr();
+ entry = obj->entryPoint();
+
+ // If load_addr_mask is set to 0x0, then calculate the smallest mask to
+ // cover all kernel addresses so gem5 can relocate the kernel to a new
+ // offset.
+ if (loadAddrMask == 0)
+ loadAddrMask = mask(findMsbSet(end - start) + 1);
+
+ image.move([this](Addr a) {
+ return (a & loadAddrMask) + loadAddrOffset;
+ });
+
+ // load symbols
+ fatal_if(!obj->loadGlobalSymbols(symtab),
+ "Could not load kernel symbols.");
+
+ fatal_if(!obj->loadLocalSymbols(symtab),
+ "Could not load kernel local symbols.");
+
+ fatal_if(!obj->loadGlobalSymbols(debugSymbolTable),
+ "Could not load kernel symbols.");
+
+ fatal_if(!obj->loadLocalSymbols(debugSymbolTable),
+ "Could not load kernel local symbols.");
+ }
+
+ // Loading only needs to happen once and after memory system is
+ // connected so it will happen in initState()
+
+ std::vector<Addr> extras_addrs = p.extras_addrs;
+ if (extras_addrs.empty())
+ extras_addrs.resize(p.extras.size(), MaxAddr);
+ fatal_if(p.extras.size() != extras_addrs.size(),
+ "Additional kernel objects, not all load addresses specified\n");
+ for (int ker_idx = 0; ker_idx < p.extras.size(); ker_idx++) {
+ const std::string &obj_name = p.extras[ker_idx];
+ const bool raw = extras_addrs[ker_idx] != MaxAddr;
+ ObjectFile *obj = createObjectFile(obj_name, raw);
+ fatal_if(!obj, "Failed to build additional kernel object '%s'.\n",
+ obj_name);
+ extras.push_back(obj);
+ }
+}
+
+Addr
+OsKernel::fixFuncEventAddr(Addr addr)
+{
+ return system->fixFuncEventAddr(addr);
+}
+
+OsKernel::~OsKernel()
+{
+ delete symtab;
+}
+
+void
+OsKernel::initState()
+{
+ auto &phys_mem = system->physProxy;
+ /**
+ * Load the kernel code into memory.
+ */
+ auto mapper = [this](Addr a) {
+ return (a & loadAddrMask) + loadAddrOffset;
+ };
+ if (params().object_file != "") {
+ if (params().addr_check) {
+ // Validate kernel mapping before loading binary
+ fatal_if(!system->isMemAddr(mapper(start)) ||
+ !system->isMemAddr(mapper(end)),
+ "Kernel is mapped to invalid location (not memory). "
+ "start (%#x) - end (%#x) %#x:%#x\n",
+ start, end, mapper(start), mapper(end));
+ }
+ // Load program sections into memory
+ image.write(phys_mem);
+
+ DPRINTF(Loader, "Kernel start = %#x\n", start);
+ DPRINTF(Loader, "Kernel end = %#x\n", end);
+ DPRINTF(Loader, "Kernel entry = %#x\n", entry);
+ DPRINTF(Loader, "Kernel loaded...\n");
+ }
+
+ std::vector<Addr> extras_addrs = params().extras_addrs;
+ if (extras_addrs.empty())
+ extras_addrs.resize(params().extras.size(), MaxAddr);
+ for (int idx = 0; idx < extras.size(); idx++) {
+ const Addr load_addr = extras_addrs[idx];
+ auto image = extras[idx]->buildImage();
+ if (load_addr != MaxAddr)
+ image = image.offset(load_addr);
+ else
+ image = image.move(mapper);
+ image.write(phys_mem);
+ }
+}
+
+void
+OsKernel::serialize(CheckpointOut &cp) const
+{
+ symtab->serialize("symtab", cp);
+ serializeSymtab(cp);
+}
+
+void
+OsKernel::unserialize(CheckpointIn &cp)
+{
+ symtab->unserialize("symtab", cp);
+ unserializeSymtab(cp);
+}
+
+OsKernel *
+OsKernelParams::create()
+{
+ return new OsKernel(*this);
+}
--- /dev/null
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * 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.
+ */
+
+#ifndef __SIM_OS_KERNEL_HH__
+#define __SIM_OS_KERNEL_HH__
+
+#include "base/loader/memory_image.hh"
+#include "base/loader/symtab.hh"
+#include "params/OsKernel.hh"
+#include "sim/sim_object.hh"
+
+class ObjectFile;
+class SymbolTable;
+class System;
+
+class OsKernel : public SimObject
+{
+ public:
+ using Params = OsKernelParams;
+
+ protected:
+ const Params &_params;
+
+ Addr fixFuncEventAddr(Addr);
+
+ public:
+ OsKernel(const Params &p);
+ ~OsKernel();
+
+ const Params ¶ms() { return _params; }
+
+ void initState() override;
+
+ const std::string commandLine;
+
+ void serialize(CheckpointOut &cp) const override;
+ void unserialize(CheckpointIn &cp) override;
+
+ System *system = nullptr;
+
+ ObjectFile *obj = nullptr;
+ SymbolTable *symtab = nullptr;
+
+ MemoryImage image;
+
+ Addr start = 0;
+ Addr end = MaxAddr;
+ Addr entry = 0;
+
+ /** Mask that should be anded for binary/symbol loading.
+ * This allows one two different OS requirements for the same ISA to be
+ * handled. Some OSes are compiled for a virtual address and need to be
+ * loaded into physical memory that starts at address 0, while other
+ * bare metal tools generate images that start at address 0.
+ */
+ Addr loadAddrMask;
+
+ /** Offset that should be used for binary/symbol loading.
+ * This further allows more flexibility than the loadAddrMask allows alone
+ * in loading kernels and similar. The loadAddrOffset is applied after the
+ * loadAddrMask.
+ */
+ Addr loadAddrOffset;
+
+ std::vector<ObjectFile *> extras;
+
+ /** @{ */
+ /**
+ * Add a function-based event to the given function, to be looked
+ * up in the specified symbol table.
+ *
+ * The ...OrPanic flavor of the method causes the simulator to
+ * panic if the symbol can't be found.
+ *
+ * @param symtab Symbol table to use for look up.
+ * @param lbl Function to hook the event to.
+ * @param desc Description to be passed to the event.
+ * @param args Arguments to be forwarded to the event constructor.
+ */
+ template <class T, typename... Args>
+ T *
+ addFuncEvent(const SymbolTable *symtab, const char *lbl,
+ const std::string &desc, Args... args)
+ {
+ Addr addr M5_VAR_USED = 0; // initialize only to avoid compiler warning
+
+ if (symtab->findAddress(lbl, addr)) {
+ return new T(system, desc, fixFuncEventAddr(addr),
+ std::forward<Args>(args)...);
+ }
+
+ return nullptr;
+ }
+
+ template <class T>
+ T *
+ addFuncEvent(const SymbolTable *symtab, const char *lbl)
+ {
+ return addFuncEvent<T>(symtab, lbl, lbl);
+ }
+
+ template <class T, typename... Args>
+ T *
+ addFuncEventOrPanic(const SymbolTable *symtab, const char *lbl,
+ Args... args)
+ {
+ T *e = addFuncEvent<T>(symtab, lbl, std::forward<Args>(args)...);
+ panic_if(!e, "Failed to find symbol '%s'", lbl);
+ return e;
+ }
+ /** @} */
+
+ /** @{ */
+ /**
+ * Add a function-based event to a kernel symbol.
+ *
+ * These functions work like their addFuncEvent() and
+ * addFuncEventOrPanic() counterparts. The only difference is that
+ * they automatically use the kernel symbol table. All arguments
+ * are forwarded to the underlying method.
+ *
+ * @see addFuncEvent()
+ * @see addFuncEventOrPanic()
+ *
+ * @param lbl Function to hook the event to.
+ * @param args Arguments to be passed to addFuncEvent
+ */
+ template <class T, typename... Args>
+ T *
+ addKernelFuncEvent(const char *lbl, Args... args)
+ {
+ return addFuncEvent<T>(symtab, lbl, std::forward<Args>(args)...);
+ }
+
+ template <class T, typename... Args>
+ T *
+ addKernelFuncEventOrPanic(const char *lbl, Args... args)
+ {
+ T *e(addFuncEvent<T>(symtab, lbl, std::forward<Args>(args)...));
+ if (!e)
+ panic("Failed to find kernel symbol '%s'", lbl);
+ return e;
+ }
+ /** @} */
+
+ protected:
+ /**
+ * If needed, serialize additional symbol table entries for a
+ * specific subclass of this system.
+ *
+ * @param os stream to serialize to
+ */
+ virtual void serializeSymtab(CheckpointOut &os) const {}
+
+ /**
+ * If needed, unserialize additional symbol table entries for a
+ * specific subclass of this system.
+ *
+ * @param cp checkpoint to unserialize from
+ * @param section relevant section in the checkpoint
+ */
+ virtual void unserializeSymtab(CheckpointIn &cp) {}
+};
+
+#endif // __SIM_OS_KERNEL_HH__
if (!to_number(address, addr))
continue;
- if (!tc->getSystemPtr()->kernelSymtab->insert(addr, symbol))
+ if (!tc->getSystemPtr()->workload->symtab->insert(addr, symbol))
continue;
DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
- tc->getSystemPtr()->kernelSymtab->insert(addr,symbol);
+ tc->getSystemPtr()->workload->symtab->insert(addr,symbol);
debugSymbolTable->insert(addr,symbol);
}
pagePtr(0),
init_param(p->init_param),
physProxy(_systemPort, p->cache_line_size),
- kernelSymtab(nullptr),
- kernel(nullptr),
- loadAddrMask(p->load_addr_mask),
- loadAddrOffset(p->load_offset),
+ workload(p->workload),
#if USE_KVM
kvmVM(p->kvm_vm),
#else
totalNumInsts(0),
redirectPaths(p->redirect_paths)
{
+ if (workload)
+ workload->system = this;
// add self to global system list
systemList.push_back(this);
}
#endif
- if (FullSystem) {
- kernelSymtab = new SymbolTable;
- if (!debugSymbolTable)
- debugSymbolTable = new SymbolTable;
- }
-
// check if the cache line size is a value known to work
if (!(_cacheLineSize == 16 || _cacheLineSize == 32 ||
_cacheLineSize == 64 || _cacheLineSize == 128))
tmp_id = getMasterId(this, "interrupt");
assert(tmp_id == Request::intMasterId);
- if (FullSystem) {
- if (params()->kernel == "") {
- inform("No kernel set for full system simulation. "
- "Assuming you know what you're doing\n");
- } else {
- // Get the kernel code
- kernel = createObjectFile(params()->kernel);
- inform("kernel located at: %s", params()->kernel);
-
- if (kernel == NULL)
- fatal("Could not load kernel file %s", params()->kernel);
-
- kernelImage = kernel->buildImage();
-
- // setup entry points
- kernelStart = kernelImage.minAddr();
- kernelEnd = kernelImage.maxAddr();
- kernelEntry = kernel->entryPoint();
-
- // If load_addr_mask is set to 0x0, then auto-calculate
- // the smallest mask to cover all kernel addresses so gem5
- // can relocate the kernel to a new offset.
- if (loadAddrMask == 0) {
- Addr shift_amt = findMsbSet(kernelEnd - kernelStart) + 1;
- loadAddrMask = ((Addr)1 << shift_amt) - 1;
- }
-
- kernelImage.move([this](Addr a) {
- return (a & loadAddrMask) + loadAddrOffset;
- });
-
- // load symbols
- if (!kernel->loadGlobalSymbols(kernelSymtab))
- fatal("could not load kernel symbols\n");
-
- if (!kernel->loadLocalSymbols(kernelSymtab))
- fatal("could not load kernel local symbols\n");
-
- if (!kernel->loadGlobalSymbols(debugSymbolTable))
- fatal("could not load kernel symbols\n");
-
- if (!kernel->loadLocalSymbols(debugSymbolTable))
- fatal("could not load kernel local symbols\n");
-
- // Loading only needs to happen once and after memory system is
- // connected so it will happen in initState()
- }
-
- if (p->kernel_extras_addrs.empty())
- p->kernel_extras_addrs.resize(p->kernel_extras.size(), MaxAddr);
- fatal_if(p->kernel_extras.size() != p->kernel_extras_addrs.size(),
- "Additional kernel objects, not all load addresses specified\n");
- for (int ker_idx = 0; ker_idx < p->kernel_extras.size(); ker_idx++) {
- const std::string &obj_name = p->kernel_extras[ker_idx];
- const bool raw = p->kernel_extras_addrs[ker_idx] != MaxAddr;
- ObjectFile *obj = createObjectFile(obj_name, raw);
- fatal_if(!obj, "Failed to build additional kernel object '%s'.\n",
- obj_name);
- kernelExtras.push_back(obj);
- }
- }
-
// increment the number of running systems
numSystemsRunning++;
System::~System()
{
- delete kernelSymtab;
- delete kernel;
-
for (uint32_t j = 0; j < numWorkIds; j++)
delete workItemStats[j];
}
);
}
-void
-System::initState()
-{
- if (FullSystem) {
- // Moved from the constructor to here since it relies on the
- // address map being resolved in the interconnect
- /**
- * Load the kernel code into memory
- */
- auto mapper = [this](Addr a) {
- return (a & loadAddrMask) + loadAddrOffset;
- };
- if (params()->kernel != "") {
- if (params()->kernel_addr_check) {
- // Validate kernel mapping before loading binary
- if (!isMemAddr(mapper(kernelStart)) ||
- !isMemAddr(mapper(kernelEnd))) {
- fatal("Kernel is mapped to invalid location (not memory). "
- "kernelStart 0x(%x) - kernelEnd 0x(%x) %#x:%#x\n",
- kernelStart, kernelEnd,
- mapper(kernelStart), mapper(kernelEnd));
- }
- }
- // Load program sections into memory
- kernelImage.write(physProxy);
-
- DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
- DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd);
- DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
- DPRINTF(Loader, "Kernel loaded...\n");
- }
- std::function<Addr(Addr)> extra_mapper;
- for (auto ker_idx = 0; ker_idx < kernelExtras.size(); ker_idx++) {
- const Addr load_addr = params()->kernel_extras_addrs[ker_idx];
- auto image = kernelExtras[ker_idx]->buildImage();
- if (load_addr != MaxAddr)
- image = image.offset(load_addr);
- else
- image = image.move(mapper);
- image.write(physProxy);
- }
- }
-}
-
void
System::replaceThreadContext(ThreadContext *tc, ContextID context_id)
{
void
System::serialize(CheckpointOut &cp) const
{
- if (FullSystem)
- kernelSymtab->serialize("kernel_symtab", cp);
SERIALIZE_SCALAR(pagePtr);
- serializeSymtab(cp);
// also serialize the memories in the system
physmem.serializeSection(cp, "physmem");
void
System::unserialize(CheckpointIn &cp)
{
- if (FullSystem)
- kernelSymtab->unserialize("kernel_symtab", cp);
UNSERIALIZE_SCALAR(pagePtr);
- unserializeSymtab(cp);
// also unserialize the memories in the system
physmem.unserializeSection(cp, "physmem");
#include "mem/port_proxy.hh"
#include "params/System.hh"
#include "sim/futex_map.hh"
+#include "sim/os_kernel.hh"
#include "sim/redirect_path.hh"
#include "sim/se_signal.hh"
#include "sim/sim_object.hh"
* boot.*/
PortProxy physProxy;
- /** kernel symbol table */
- SymbolTable *kernelSymtab;
-
- /** Object pointer for the kernel code */
- ObjectFile *kernel;
- MemoryImage kernelImage;
-
- /** Additional object files */
- std::vector<ObjectFile *> kernelExtras;
-
- /** Beginning of kernel code */
- Addr kernelStart;
-
- /** End of kernel code */
- Addr kernelEnd;
-
- /** Entry point in the kernel to start at */
- Addr kernelEntry;
-
- /** Mask that should be anded for binary/symbol loading.
- * This allows one two different OS requirements for the same ISA to be
- * handled. Some OSes are compiled for a virtual address and need to be
- * loaded into physical memory that starts at address 0, while other
- * bare metal tools generate images that start at address 0.
- */
- Addr loadAddrMask;
-
- /** Offset that should be used for binary/symbol loading.
- * This further allows more flexibility than the loadAddrMask allows alone
- * in loading kernels and similar. The loadAddrOffset is applied after the
- * loadAddrMask.
- */
- Addr loadAddrOffset;
+ /** OS kernel */
+ OsKernel *workload = nullptr;
public:
/**
panic("Base fixFuncEventAddr not implemented.\n");
}
- /** @{ */
- /**
- * Add a function-based event to the given function, to be looked
- * up in the specified symbol table.
- *
- * The ...OrPanic flavor of the method causes the simulator to
- * panic if the symbol can't be found.
- *
- * @param symtab Symbol table to use for look up.
- * @param lbl Function to hook the event to.
- * @param desc Description to be passed to the event.
- * @param args Arguments to be forwarded to the event constructor.
- */
- template <class T, typename... Args>
- T *addFuncEvent(const SymbolTable *symtab, const char *lbl,
- const std::string &desc, Args... args)
- {
- Addr addr M5_VAR_USED = 0; // initialize only to avoid compiler warning
-
- if (symtab->findAddress(lbl, addr)) {
- T *ev = new T(this, desc, fixFuncEventAddr(addr),
- std::forward<Args>(args)...);
- return ev;
- }
-
- return NULL;
- }
-
- template <class T>
- T *addFuncEvent(const SymbolTable *symtab, const char *lbl)
- {
- return addFuncEvent<T>(symtab, lbl, lbl);
- }
-
- template <class T, typename... Args>
- T *addFuncEventOrPanic(const SymbolTable *symtab, const char *lbl,
- Args... args)
- {
- T *e(addFuncEvent<T>(symtab, lbl, std::forward<Args>(args)...));
- if (!e)
- panic("Failed to find symbol '%s'", lbl);
- return e;
- }
- /** @} */
-
- /** @{ */
- /**
- * Add a function-based event to a kernel symbol.
- *
- * These functions work like their addFuncEvent() and
- * addFuncEventOrPanic() counterparts. The only difference is that
- * they automatically use the kernel symbol table. All arguments
- * are forwarded to the underlying method.
- *
- * @see addFuncEvent()
- * @see addFuncEventOrPanic()
- *
- * @param lbl Function to hook the event to.
- * @param args Arguments to be passed to addFuncEvent
- */
- template <class T, typename... Args>
- T *addKernelFuncEvent(const char *lbl, Args... args)
- {
- return addFuncEvent<T>(kernelSymtab, lbl,
- std::forward<Args>(args)...);
- }
-
- template <class T, typename... Args>
- T *addKernelFuncEventOrPanic(const char *lbl, Args... args)
- {
- T *e(addFuncEvent<T>(kernelSymtab, lbl,
- std::forward<Args>(args)...));
- if (!e)
- panic("Failed to find kernel symbol '%s'", lbl);
- return e;
- }
- /** @} */
-
public:
std::vector<BaseRemoteGDB *> remoteGDB;
bool breakpoint();
System(Params *p);
~System();
- void initState() override;
-
const Params *params() const { return (const Params *)_params; }
/**
public:
- /**
- * Returns the address the kernel starts at.
- * @return address the kernel starts at
- */
- Addr getKernelStart() const { return kernelStart; }
-
- /**
- * Returns the address the kernel ends at.
- * @return address the kernel ends at
- */
- Addr getKernelEnd() const { return kernelEnd; }
-
- /**
- * Returns the address the entry point to the kernel code.
- * @return entry point of the kernel code
- */
- Addr getKernelEntry() const { return kernelEntry; }
-
/// Allocate npages contiguous unused physical pages
/// @return Starting address of first page
Addr allocPhysPages(int npages);
// to be redirected to the faux-filesystem (a duplicate filesystem
// intended to replace certain files on the host filesystem).
std::vector<RedirectPath*> redirectPaths;
-
- protected:
-
- /**
- * If needed, serialize additional symbol table entries for a
- * specific subclass of this system. Currently this is used by
- * Alpha and MIPS.
- *
- * @param os stream to serialize to
- */
- virtual void serializeSymtab(CheckpointOut &os) const {}
-
- /**
- * If needed, unserialize additional symbol table entries for a
- * specific subclass of this system.
- *
- * @param cp checkpoint to unserialize from
- * @param section relevant section in the checkpoint
- */
- virtual void unserializeSymtab(CheckpointIn &cp) {}
};
void printSystems();
# We typically want the simulator to panic if the kernel
# panics or oopses. This prevents the simulator from running
# an obviously failed test case until the end of time.
- system.panic_on_panic = True
- system.panic_on_oops = True
+ system.workload.panic_on_panic = True
+ system.workload.panic_on_oops = True
- system.kernel = SysPaths.binary(default_kernels[self.machine_type])
+ system.workload.object_file = SysPaths.binary(
+ default_kernels[self.machine_type])
self.init_system(system)
- system.generateDtb(m5.options.outdir, 'system.dtb')
+ system.workload.dtb_filename = \
+ os.path.join(m5.options.outdir, 'system.dtb')
+ system.generateDtb(system.workload.dtb_filename)
return system
class LinuxArmFSSystem(LinuxArmSystemBuilder,