config,arch,cpu,kern,sim: Extract kernel information from System.
authorGabe Black <gabeblack@google.com>
Tue, 29 Oct 2019 01:55:02 +0000 (18:55 -0700)
committerGabe Black <gabeblack@google.com>
Wed, 11 Mar 2020 15:57:14 +0000 (15:57 +0000)
Information about what kernel to load and how to load it was built
into the System object and its subclasses. That overloaded the System
object and made it responsible for too many things, and also was
somewhat awkward when working with SE mode which doesn't have a kernel.

This change extracts the kernel and information related to it from the
System object and puts into into a OsKernel or Workload object.
Currently the idea of a "Workload" to run and a kernel are a bit
muddled, an unfortunate carry-over from the original code. It's also an
implication of trying not to make too sweeping of a change, and to
minimize the number of times configs need to change, ie avoiding
creating a "kernel" parameter which would shortly thereafter be
renamed to "workload".

In future changes, the ideas of a kernel and a workload will be
disentangled, and workloads will be expanded to include emulated
operating systems which shephard and contain Process-es for syscall
emulation.

This change was originally split into pieces to make reviewing it
easier. Those reviews are here:

https: //gem5-review.googlesource.com/c/public/gem5/+/22243
https: //gem5-review.googlesource.com/c/public/gem5/+/24144
https: //gem5-review.googlesource.com/c/public/gem5/+/24145
https: //gem5-review.googlesource.com/c/public/gem5/+/24146
https: //gem5-review.googlesource.com/c/public/gem5/+/24147
https: //gem5-review.googlesource.com/c/public/gem5/+/24286

Change-Id: Ia3d863db276a023b6a2c7ee7a656d8142ff75589
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/26466
Reviewed-by: Gabe Black <gabeblack@google.com>
Maintainer: Gabe Black <gabeblack@google.com>
Tested-by: kokoro <noreply+kokoro@google.com>
69 files changed:
configs/common/FSConfig.py
configs/common/MemConfig.py
configs/example/arm/baremetal.py
configs/example/arm/fs_bigLITTLE.py
configs/example/arm/starter_fs.py
configs/example/fs.py
configs/example/se.py
src/arch/arm/ArmFsWorkload.py [new file with mode: 0644]
src/arch/arm/ArmSystem.py
src/arch/arm/SConscript
src/arch/arm/freebsd/fs_workload.cc [new file with mode: 0644]
src/arch/arm/freebsd/fs_workload.hh [new file with mode: 0644]
src/arch/arm/freebsd/system.cc [deleted file]
src/arch/arm/freebsd/system.hh [deleted file]
src/arch/arm/fs_workload.cc [new file with mode: 0644]
src/arch/arm/fs_workload.hh [new file with mode: 0644]
src/arch/arm/linux/fs_workload.cc [new file with mode: 0644]
src/arch/arm/linux/fs_workload.hh [new file with mode: 0644]
src/arch/arm/linux/system.cc [deleted file]
src/arch/arm/linux/system.hh [deleted file]
src/arch/arm/stacktrace.cc
src/arch/arm/system.cc
src/arch/arm/system.hh
src/arch/generic/linux/threadinfo.hh
src/arch/mips/MipsSystem.py
src/arch/riscv/RiscvFsWorkload.py [new file with mode: 0644]
src/arch/riscv/RiscvSystem.py
src/arch/riscv/SConscript
src/arch/riscv/bare_metal/fs_workload.cc [new file with mode: 0644]
src/arch/riscv/bare_metal/fs_workload.hh [new file with mode: 0644]
src/arch/riscv/faults.cc
src/arch/riscv/fs_workload.hh [new file with mode: 0644]
src/arch/riscv/system.cc
src/arch/riscv/system.hh
src/arch/riscv/tlb.cc
src/arch/sparc/SConscript
src/arch/sparc/SparcFsWorkload.py [new file with mode: 0644]
src/arch/sparc/SparcSystem.py
src/arch/sparc/fs_workload.cc [new file with mode: 0644]
src/arch/sparc/fs_workload.hh [new file with mode: 0644]
src/arch/sparc/system.cc
src/arch/sparc/system.hh
src/arch/x86/SConscript
src/arch/x86/X86FsWorkload.py [new file with mode: 0644]
src/arch/x86/X86System.py
src/arch/x86/fs_workload.cc [new file with mode: 0644]
src/arch/x86/fs_workload.hh [new file with mode: 0644]
src/arch/x86/linux/fs_workload.cc [new file with mode: 0644]
src/arch/x86/linux/fs_workload.hh [new file with mode: 0644]
src/arch/x86/linux/system.cc [deleted file]
src/arch/x86/linux/system.hh [deleted file]
src/arch/x86/process.cc
src/arch/x86/pseudo_inst.cc
src/arch/x86/stacktrace.cc
src/arch/x86/system.cc
src/arch/x86/system.hh
src/cpu/o3/thread_state.hh
src/cpu/simple_thread.cc
src/dev/arm/RealView.py
src/kern/linux/helpers.cc
src/sim/OsKernel.py [new file with mode: 0644]
src/sim/SConscript
src/sim/System.py
src/sim/os_kernel.cc [new file with mode: 0644]
src/sim/os_kernel.hh [new file with mode: 0644]
src/sim/pseudo_inst.cc
src/sim/system.cc
src/sim/system.hh
tests/configs/arm_generic.py

index 691a04a27b3fa9a99a0a0eaa5fd46e08ae1cf848..b58c273804cf2adf89a39e08f59b4d925586691b 100644 (file)
@@ -123,10 +123,6 @@ def makeSparcSystem(mem_mode, mdesc=None, cmdline=None):
                        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])
@@ -150,15 +146,37 @@ def makeSparcSystem(mem_mode, mdesc=None, cmdline=None):
         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,
@@ -169,10 +187,7 @@ 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
@@ -242,11 +257,13 @@ def makeArmSystem(mem_mode, machine_type, num_cpus=1, mdesc=None,
         # 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:
@@ -254,8 +271,6 @@ def makeArmSystem(mem_mode, machine_type, num_cpus=1, mdesc=None,
                       '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
 
@@ -292,7 +307,11 @@ def makeArmSystem(mem_mode, machine_type, num_cpus=1, mdesc=None,
                            "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
@@ -381,7 +400,7 @@ def makeLinuxMipsSystem(mem_mode, mdesc=None, cmdline=None):
     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
 
@@ -445,9 +464,12 @@ def connectX86RubySystem(x86_sys):
     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
@@ -489,7 +511,7 @@ def makeX86System(mem_mode, numCPUs=1, mdesc=None, self=None, Ruby=False):
 
     # 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 = []
@@ -509,8 +531,8 @@ def makeX86System(mem_mode, numCPUs=1, mdesc=None, self=None, Ruby=False):
     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   ')
@@ -550,15 +572,15 @@ def makeX86System(mem_mode, numCPUs=1, mdesc=None, self=None, Ruby=False):
     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.
@@ -596,12 +618,12 @@ def makeLinuxX86System(mem_mode, numCPUs=1, mdesc=None, Ruby=False,
         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
 
 
index 85494d3f3cb43e080f64e4ee639fc08763cf41e3..d1cc6558a08e7150397f287ac9ea33718daefe7e 100644 (file)
@@ -125,7 +125,7 @@ def config_mem(options, system):
             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:
@@ -133,7 +133,7 @@ def config_mem(options, 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
index 109370b432140402f648afd432ddeb7c7a4e5ac9..c1628934bd79b3618e51a2229d9b9dcb6c348286 100644 (file)
@@ -98,7 +98,8 @@ def create(args):
                                   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)
@@ -215,7 +216,7 @@ def main():
 
     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)
 
index cc3e748c887f2bf7266ec1b8a3ac46d8206452c9..b7e794d58ca343a983fd6b6fcce522247dd92dc3 100644 (file)
@@ -118,9 +118,10 @@ def createSystem(caches, kernel, bootscript, machine_type="VExpress_GEM5",
     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)
@@ -243,9 +244,9 @@ def build(options):
 
     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")
@@ -287,9 +288,11 @@ def build(options):
 
     # 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
index ee67cb0b406fc81ac02c16ccf7187f1c7446195c..7a202807e758476dab4d22c42dc9f9dde2799baf 100644 (file)
@@ -99,11 +99,13 @@ def create(args):
     # 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)
@@ -146,10 +148,12 @@ def create(args):
     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 = [
@@ -161,13 +165,13 @@ def create(args):
         # 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
 
index bf68325482ae6f84c8593d0acbd47222db34be8c..5264aa568cc7b77f50a9d309a63acae86688bd4c 100644 (file)
@@ -124,7 +124,7 @@ def build_test_system(np):
                                              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
@@ -269,7 +269,7 @@ def build_drive_system(np):
     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()
@@ -369,7 +369,9 @@ if buildEnv['TARGET_ISA'] == "arm" and not options.bare_metal \
     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)
index 25c148882fe7aaf966ddd085292f7455d01c24f4..a3cd6f14da95ce342c04a79acaf2f0e51b991b7a 100644 (file)
@@ -50,6 +50,7 @@ import os
 import m5
 from m5.defines import buildEnv
 from m5.objects import *
+from m5.params import NULL
 from m5.util import addToPath, fatal, warn
 
 addToPath('../')
@@ -171,7 +172,8 @@ np = options.num_cpus
 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
diff --git a/src/arch/arm/ArmFsWorkload.py b/src/arch/arm/ArmFsWorkload.py
new file mode 100644 (file)
index 0000000..6064d81
--- /dev/null
@@ -0,0 +1,90 @@
+# 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"
index 5f4061feb8a4383905f668c6eaa45a7d8b8bbca4..1b5fc907dd05d827b471c5e9e387c593024672f7 100644 (file)
@@ -41,23 +41,12 @@ from m5.util.fdthelper import *
 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,
@@ -90,10 +79,11 @@ class ArmSystem(System):
     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.
@@ -103,8 +93,7 @@ class ArmSystem(System):
 
         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):
@@ -139,37 +128,3 @@ class ArmSystem(System):
                 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"
index b4e9bba8e11e95184680d32e381f9c66ffd510b0..409e287db64944c9389bc7dd80ec2920f1814280 100644 (file)
@@ -67,10 +67,11 @@ if env['TARGET_ISA'] == 'arm':
     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')
@@ -89,6 +90,7 @@ if env['TARGET_ISA'] == 'arm':
     Source('utility.cc')
     Source('vtophys.cc')
 
+    SimObject('ArmFsWorkload.py')
     SimObject('ArmInterrupts.py')
     SimObject('ArmISA.py')
     SimObject('ArmNativeTrace.py')
diff --git a/src/arch/arm/freebsd/fs_workload.cc b/src/arch/arm/freebsd/fs_workload.cc
new file mode 100644 (file)
index 0000000..c248ff6
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * 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);
+}
diff --git a/src/arch/arm/freebsd/fs_workload.hh b/src/arch/arm/freebsd/fs_workload.hh
new file mode 100644 (file)
index 0000000..7f0ac08
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * 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__
diff --git a/src/arch/arm/freebsd/system.cc b/src/arch/arm/freebsd/system.cc
deleted file mode 100644 (file)
index b771267..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * 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);
-}
diff --git a/src/arch/arm/freebsd/system.hh b/src/arch/arm/freebsd/system.hh
deleted file mode 100644 (file)
index f4f19a3..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * 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__
-
diff --git a/src/arch/arm/fs_workload.cc b/src/arch/arm/fs_workload.cc
new file mode 100644 (file)
index 0000000..befba3a
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * 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);
+}
diff --git a/src/arch/arm/fs_workload.hh b/src/arch/arm/fs_workload.hh
new file mode 100644 (file)
index 0000000..936ddd7
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * 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__
diff --git a/src/arch/arm/linux/fs_workload.cc b/src/arch/arm/linux/fs_workload.cc
new file mode 100644 (file)
index 0000000..3f5744b
--- /dev/null
@@ -0,0 +1,362 @@
+/*
+ * 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);
+}
diff --git a/src/arch/arm/linux/fs_workload.hh b/src/arch/arm/linux/fs_workload.hh
new file mode 100644 (file)
index 0000000..aa771c8
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * 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__
+
diff --git a/src/arch/arm/linux/system.cc b/src/arch/arm/linux/system.cc
deleted file mode 100644 (file)
index 30393c4..0000000
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * 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);
-}
-
diff --git a/src/arch/arm/linux/system.hh b/src/arch/arm/linux/system.hh
deleted file mode 100644 (file)
index 21ce37d..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * 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__
-
index 9280e1caadeb35825318675df90c3cc998f164e1..5decb145dcda352a74600d8a017aaa01ed1aadf5 100644 (file)
@@ -46,7 +46,7 @@ static int32_t
 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))
index 56ee98ded67a0ca9018e7298202ce7dd95dd09b8..6ecc75a6a1f767a5d12bb91a84642b16e382afd8 100644 (file)
@@ -42,7 +42,7 @@
 
 #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"
@@ -56,16 +56,12 @@ using namespace Linux;
 
 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),
@@ -76,107 +72,36 @@ ArmSystem::ArmSystem(Params *p)
       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
@@ -185,24 +110,6 @@ ArmSystem::haveSecurity(ThreadContext *tc)
     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)
 {
@@ -295,20 +202,3 @@ ArmSystemParams::create()
 {
     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);
-}
index 6331af283bd64b51f40a54ecf912b2c79f6d8a6b..0c75ad51d9bb5a1a585379e2587b06c8c4f19e38 100644 (file)
@@ -47,7 +47,6 @@
 
 #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"
@@ -59,20 +58,6 @@ class ThreadContext;
 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
      */
@@ -102,7 +87,7 @@ class ArmSystem : public System
     /**
      * Reset address (ARMv8)
      */
-    const Addr _resetAddr;
+    Addr _resetAddr;
 
     /**
      * True if the register width of the highest implemented exception level is
@@ -142,16 +127,6 @@ class ArmSystem : public System
      */
     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 *
@@ -161,20 +136,13 @@ class ArmSystem : public System
     }
 
     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 */
@@ -198,16 +166,14 @@ class ArmSystem : public 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; }
@@ -220,7 +186,8 @@ class ArmSystem : public System
     bool highestELIs64() const { return _highestELIs64; }
 
     /** Returns the highest implemented exception level */
-    ExceptionLevel highestEL() const
+    ExceptionLevel
+    highestEL() const
     {
         if (_haveSecurity)
             return EL3;
@@ -232,6 +199,7 @@ class ArmSystem : public System
     /** 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; }
@@ -253,7 +221,8 @@ class ArmSystem : public System
     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;
@@ -263,10 +232,7 @@ class ArmSystem : public System
     }
 
     /** 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; }
@@ -341,23 +307,4 @@ class ArmSystem : public System
                                       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
index 75c936d5c9ecefef04acfb7b79fb861a443a14e2..971211371672a6b966632760b83e9aa307403744 100644 (file)
@@ -47,7 +47,7 @@ class ThreadInfo
     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");
index fefc582fc725846db44cc675c9112dc8eefae836..d32f30a6a0671864317cabcb5b9043ba6eef4d7d 100644 (file)
@@ -40,7 +40,6 @@ class MipsSystem(System):
     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'
diff --git a/src/arch/riscv/RiscvFsWorkload.py b/src/arch/riscv/RiscvFsWorkload.py
new file mode 100644 (file)
index 0000000..5d1db98
--- /dev/null
@@ -0,0 +1,51 @@
+# -*- 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
index 7be9ff9a3fd0d06c8dbd21e802d725aec5fe855e..c68fa8c9bbc59e945332e80cb53b3dd6f989c3c5 100644 (file)
@@ -34,14 +34,3 @@ from m5.objects.System import System
 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
index 21c084b81bc4721bde010a77aa00e7b2286c787e..4679102f0b0bed97a7d2d4cb383b925266d653a9 100644 (file)
@@ -57,8 +57,9 @@ if env['TARGET_ISA'] == 'riscv':
     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')
diff --git a/src/arch/riscv/bare_metal/fs_workload.cc b/src/arch/riscv/bare_metal/fs_workload.cc
new file mode 100644 (file)
index 0000000..5c03128
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * 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);
+}
diff --git a/src/arch/riscv/bare_metal/fs_workload.hh b/src/arch/riscv/bare_metal/fs_workload.hh
new file mode 100644 (file)
index 0000000..722806d
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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__
index df8c0aed77b065e3ced2ae3cd238b2ad2f93d2cb..1d48d85dbaca50b684f76abb32e76d568e63ddc8 100644 (file)
@@ -30,9 +30,9 @@
 
 #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"
@@ -146,7 +146,8 @@ void Reset::invoke(ThreadContext *tc, const StaticInstPtr &inst)
     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);
 }
 
diff --git a/src/arch/riscv/fs_workload.hh b/src/arch/riscv/fs_workload.hh
new file mode 100644 (file)
index 0000000..aaa9d0f
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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__
index 01ecbdc6d80067f49e7fbb619c0d69dd4cc0a0b7..fe234054c7f9ae5a845b42ea4f7aa3c3842422e1 100644 (file)
 
 #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()
index 62999cf57b405455ab453f45485d147e43cb1f07..fa4f766234f18456877dec3acea27b01e2a599b3 100644 (file)
 #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
index 014e3698ca1a5c712eb03c119672d94ffa123450..aefa2dfb305fabd2c7d51ac9fa91a6feaf3abbbc 100644 (file)
@@ -33,6 +33,7 @@
 #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"
@@ -285,7 +286,9 @@ TLB::translateInst(const RequestPtr &req, ThreadContext *tc)
          * 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) {
@@ -320,7 +323,9 @@ TLB::translateData(const RequestPtr &req, ThreadContext *tc, bool write)
          * 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) {
index 709911db8865870c41a32d4a0df7ec210fcb3636..1caf8a09a63d3dbca430cdbf6cfb308ccac7273c 100644 (file)
@@ -32,6 +32,7 @@ if env['TARGET_ISA'] == 'sparc':
     Source('asi.cc')
     Source('decoder.cc')
     Source('faults.cc')
+    Source('fs_workload.cc')
     Source('interrupts.cc')
     Source('isa.cc')
     Source('linux/linux.cc')
@@ -49,6 +50,7 @@ if env['TARGET_ISA'] == 'sparc':
     Source('utility.cc')
     Source('vtophys.cc')
 
+    SimObject('SparcFsWorkload.py')
     SimObject('SparcInterrupts.py')
     SimObject('SparcISA.py')
     SimObject('SparcNativeTrace.py')
diff --git a/src/arch/sparc/SparcFsWorkload.py b/src/arch/sparc/SparcFsWorkload.py
new file mode 100644 (file)
index 0000000..7f4677e
--- /dev/null
@@ -0,0 +1,62 @@
+# 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")
index 24ed4538faf5c0b8f059b82815008a8bcb30e9e3..5c56e1b53fd7060a91792fc515ba57c57a08a64f 100644 (file)
 
 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
diff --git a/src/arch/sparc/fs_workload.cc b/src/arch/sparc/fs_workload.cc
new file mode 100644 (file)
index 0000000..390c5cc
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * 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);
+}
diff --git a/src/arch/sparc/fs_workload.hh b/src/arch/sparc/fs_workload.hh
new file mode 100644 (file)
index 0000000..a52f03d
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * 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__
index 8f493940c69edffb0fedffe588faed0926766c3e..d06c17281d1c77f96064edd56d593e77c732992a 100644 (file)
 
 #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()
index 9c08d48bc2c95683cf9b4250517b5e38c4e9a53c..752d112d6af837eb5c0a16697022b4d379d9089e 100644 (file)
 #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
index 3e53228eb0276eabfd622d93608cbb87bcbd1c9a..093b4ee1c6be7016949475802c12e9097588ea76 100644 (file)
@@ -46,6 +46,7 @@ if env['TARGET_ISA'] == 'x86':
     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')
@@ -55,9 +56,9 @@ if env['TARGET_ISA'] == 'x86':
     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')
@@ -71,6 +72,7 @@ if env['TARGET_ISA'] == 'x86':
     Source('utility.cc')
     Source('vtophys.cc')
 
+    SimObject('X86FsWorkload.py')
     SimObject('X86ISA.py')
     SimObject('X86LocalApic.py')
     SimObject('X86NativeTrace.py')
diff --git a/src/arch/x86/X86FsWorkload.py b/src/arch/x86/X86FsWorkload.py
new file mode 100644 (file)
index 0000000..3628c94
--- /dev/null
@@ -0,0 +1,66 @@
+# 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')
index 171f76fa5728c1eb7e4275441cd5809f3568a331..e53aa2e13c22819288b6d84a7034f3348d64afff 100644 (file)
 # (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')
diff --git a/src/arch/x86/fs_workload.cc b/src/arch/x86/fs_workload.cc
new file mode 100644 (file)
index 0000000..c38fc9b
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+ * 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);
+}
diff --git a/src/arch/x86/fs_workload.hh b/src/arch/x86/fs_workload.hh
new file mode 100644 (file)
index 0000000..5b972ec
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * 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__
diff --git a/src/arch/x86/linux/fs_workload.cc b/src/arch/x86/linux/fs_workload.cc
new file mode 100644 (file)
index 0000000..7e58b9e
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * 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);
+}
diff --git a/src/arch/x86/linux/fs_workload.hh b/src/arch/x86/linux/fs_workload.hh
new file mode 100644 (file)
index 0000000..2eb4ed6
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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__
diff --git a/src/arch/x86/linux/system.cc b/src/arch/x86/linux/system.cc
deleted file mode 100644 (file)
index 91d71f7..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * 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);
-}
diff --git a/src/arch/x86/linux/system.hh b/src/arch/x86/linux/system.hh
deleted file mode 100644 (file)
index f9db0c9..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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
-
index e82df7b7fed8d70b517685d3072c78f163225ca0..3fed1d3289259fcb382459d6ca891fef3e5b27d5 100644 (file)
@@ -44,6 +44,7 @@
 #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"
index 52d8b7eb4b78b0c555a2a86fa9b2b39540641a4a..2cc67ddabbf22508b26b7cb6d800ce0f8bbaa2c4 100644 (file)
@@ -28,7 +28,8 @@
 
 #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"
index 54aa799d8657b37bd530b5fb3a89d3619927d484..4f824de6195afbe5a6d928f6e6c0422be48318c2 100644 (file)
@@ -46,7 +46,7 @@ static int32_t
 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))
@@ -190,7 +190,7 @@ void
 StackTrace::dump()
 {
     StringWrap name(tc->getCpuPtr()->name());
-    SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
+    SymbolTable *symtab = tc->getSystemPtr()->workload->symtab;
 
     DPRINTFN("------ Stack ------\n");
 
index 610b19a47a04c56b73d3095f6be8d2c1e275bb9a..9b4c8423fd7b71f5b82f56c03443ca359a824241 100644 (file)
 
 #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()
 {
index 70977b34a455998e1c9b1f3ff85b36af8391c29e..6cb0b2bbaaff87469064811069a4d5720d4d86c0 100644 (file)
 #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__
index bcd93ecae55b11b707cb579540e5cdc02418e227..b1814dbc6e9a73b23e3585c2a19bc6f94cf08b2f 100644 (file)
@@ -104,7 +104,7 @@ struct O3ThreadState : public ThreadState {
 
         if (cpu->params()->profile) {
             profile = new FunctionProfile(
-                    cpu->params()->system->kernelSymtab);
+                    cpu->params()->system->workload->symtab);
             Callback *cb =
                 new MakeCallback<O3ThreadState,
                 &O3ThreadState::dumpFuncProfile>(this);
index e87533f2759f00b865655af642651d9ce0a4dc99..30806a7c761601e9190f448234a297f6df6c95e7 100644 (file)
@@ -98,7 +98,7 @@ SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
     clearArchRegs();
 
     if (baseCpu->params()->profile) {
-        profile = new FunctionProfile(system->kernelSymtab);
+        profile = new FunctionProfile(system->workload->symtab);
         Callback *cb =
             new MakeCallback<SimpleThread,
             &SimpleThread::dumpFuncProfile>(this);
index 4fabcc3bdd5db1b20a9aaec33966d029678f5364..68a69d3ff6577d7425cabd8e4c862899dc3fa5c4 100644 (file)
@@ -619,9 +619,9 @@ class RealView(Platform):
         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
index e1174ae7a2a6a1ab8bf1ecba7d07f9a47ea618f1..a7c21837e8a7d86af822fb96b6522a70eaf62cdf 100644 (file)
@@ -93,7 +93,7 @@ Linux::dumpDmesg(ThreadContext *tc, std::ostream &os)
 {
     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;
diff --git a/src/sim/OsKernel.py b/src/sim/OsKernel.py
new file mode 100644 (file)
index 0000000..93cb74f
--- /dev/null
@@ -0,0 +1,47 @@
+# 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")
index 54a3e3a405c3e0c65eb710a8b7b6b50b353edcf1..30f04879e0c798bf37d1b5336c3cce6bcb5f04a0 100644 (file)
@@ -30,6 +30,7 @@ Import('*')
 
 SimObject('ClockedObject.py')
 SimObject('TickedObject.py')
+SimObject('OsKernel.py')
 SimObject('Root.py')
 SimObject('ClockDomain.py')
 SimObject('VoltageDomain.py')
@@ -53,6 +54,7 @@ Source('global_event.cc')
 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')
index 0162485bf2ca6f79b852d7b128085a26cfdf02ff..0d1f73055f1d04ac1b7444b3d6a073f79004074f 100644 (file)
@@ -99,21 +99,10 @@ class System(SimObject):
     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")
diff --git a/src/sim/os_kernel.cc b/src/sim/os_kernel.cc
new file mode 100644 (file)
index 0000000..317f4d3
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * 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);
+}
diff --git a/src/sim/os_kernel.hh b/src/sim/os_kernel.hh
new file mode 100644 (file)
index 0000000..b1238a1
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * 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 &params() { 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__
index 1878dde4c2c9284a7f0827618506860f31fd28dc..e30738720ef214bfc34a0e3ee20894fa8b7980c1 100644 (file)
@@ -217,7 +217,7 @@ loadsymbol(ThreadContext *tc)
         if (!to_number(address, addr))
             continue;
 
-        if (!tc->getSystemPtr()->kernelSymtab->insert(addr, symbol))
+        if (!tc->getSystemPtr()->workload->symtab->insert(addr, symbol))
             continue;
 
 
@@ -239,7 +239,7 @@ addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr)
 
     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);
 }
 
index 51e9d6dfbf209f3223308928e11e3393347d5923..0bae99aeb1f1ea6e413e67366404f2f5ed278e08 100644 (file)
@@ -88,10 +88,7 @@ System::System(Params *p)
       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
@@ -111,6 +108,8 @@ System::System(Params *p)
       totalNumInsts(0),
       redirectPaths(p->redirect_paths)
 {
+    if (workload)
+        workload->system = this;
 
     // add self to global system list
     systemList.push_back(this);
@@ -121,12 +120,6 @@ System::System(Params *p)
     }
 #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))
@@ -141,68 +134,6 @@ System::System(Params *p)
     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++;
 
@@ -213,9 +144,6 @@ System::System(Params *p)
 
 System::~System()
 {
-    delete kernelSymtab;
-    delete kernel;
-
     for (uint32_t j = 0; j < numWorkIds; j++)
         delete workItemStats[j];
 }
@@ -356,50 +284,6 @@ System::numRunningContexts()
     );
 }
 
-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)
 {
@@ -481,10 +365,7 @@ System::drainResume()
 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");
@@ -494,10 +375,7 @@ System::serialize(CheckpointOut &cp) const
 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");
index ae96be1a02599dc5629a08af5fd1d817131da203..f9a437becc267e1f8799469bbca875f644f29af5 100644 (file)
@@ -60,6 +60,7 @@
 #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"
@@ -209,39 +210,8 @@ class System : public SimObject, public PCEventScope
      * 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:
     /**
@@ -474,84 +444,6 @@ class System : public SimObject, public PCEventScope
         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();
@@ -572,8 +464,6 @@ class System : public SimObject, public PCEventScope
     System(Params *p);
     ~System();
 
-    void initState() override;
-
     const Params *params() const { return (const Params *)_params; }
 
     /**
@@ -584,24 +474,6 @@ class System : public SimObject, public PCEventScope
 
   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);
@@ -646,26 +518,6 @@ class System : public SimObject, public PCEventScope
     // 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();
index 210dd7393021b4107ad2cc88faa05cd851416ee0..6606de6bd1ec09f6d35a23a00372c623f4b98f10 100644 (file)
@@ -104,14 +104,17 @@ class LinuxArmSystemBuilder(object):
         # 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,