arch,sim,kern,dev,cpu: Create a Workload SimObject.
authorGabe Black <gabeblack@google.com>
Mon, 13 Jan 2020 01:21:32 +0000 (17:21 -0800)
committerGabe Black <gabeblack@google.com>
Wed, 22 Apr 2020 00:22:28 +0000 (00:22 +0000)
This generalized Workload SimObject is not geared towards FS or SE
simulations, although currently it's only used in FS. This gets rid
of the ARM specific highestELIs64 property (from the workload, not the
system) and replaces it with a generic getArch.

The old globally accessible kernel symtab has been replaced with a
symtab accessor which takes a ThreadContext *. The parameter isn't used
for anything for now, but in cases where there might be multiple
symbol tables to choose from (kernel vs. current user space?) the
method will now be able to distinguish which to use. This also makes
it possible for the workload to manage its symbol table with whatever
policy makes sense for it.

That method returns a const SymbolTable * since most of the time the
symbol table doesn't need to be modified. In the one case where an
external entity needs to modify the table, two pseudo instructions,
the table to modify isn't necessarily the one that's currently active.
For instance, the pseudo instruction will likely execute in user space,
but might be intended to add a symbol to the kernel in case something
like a module was loaded.

To support that usage, the workload has a generic "insertSymbol" method
which will insert the symbol in the table that "makes sense". There is
a lot of ambiguity what that means, but it's no less ambiguous than
today where we're only saved by the fact that there is generally only
one active symbol table to worry about.

This change also introduces a KernelWorkload SimObject class which
inherits from Workload and adds in kernel related members for cases
where the kernel is specified in the config and loaded by gem5 itself.
That's the common case, but the base Workload class would be used
directly when, for instance, doing a baremetal simulation or if the
kernel is loaded by software within the simulation as is the case for
SPARC FS.

Because a given architecture specific workload class needs to inherit
from either Workload or KernelWorkload, this change removes the
ability to boot ARM without a kernel. This ability should be restored
in the future.

To make having or not having a kernel more flexible, the kernel
specific members of the KernelWorkload should be factored out into
their own object which can then be attached to a workload through a
(potentially unused) property rather than inheritance.

Change-Id: Idf72615260266d7b4478d20d4035ed5a1e7aa241
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/24283
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Maintainer: Gabe Black <gabeblack@google.com>
Tested-by: kokoro <noreply+kokoro@google.com>
38 files changed:
configs/common/FSConfig.py
src/arch/arm/ArmFsWorkload.py
src/arch/arm/freebsd/fs_workload.cc
src/arch/arm/fs_workload.cc
src/arch/arm/fs_workload.hh
src/arch/arm/linux/fs_workload.cc
src/arch/arm/stacktrace.cc
src/arch/arm/system.cc
src/arch/generic/linux/threadinfo.hh
src/arch/riscv/RiscvFsWorkload.py
src/arch/riscv/bare_metal/fs_workload.cc
src/arch/riscv/bare_metal/fs_workload.hh
src/arch/riscv/bare_metal/system.cc [deleted file]
src/arch/riscv/bare_metal/system.hh [deleted file]
src/arch/riscv/fs_workload.hh
src/arch/sparc/SparcFsWorkload.py
src/arch/sparc/fs_workload.cc
src/arch/sparc/fs_workload.hh
src/arch/x86/X86FsWorkload.py
src/arch/x86/fs_workload.cc
src/arch/x86/fs_workload.hh
src/arch/x86/stacktrace.cc
src/cpu/o3/thread_state.hh
src/cpu/simple_thread.cc
src/kern/linux/helpers.cc
src/sim/OsKernel.py [deleted file]
src/sim/SConscript
src/sim/System.py
src/sim/Workload.py [new file with mode: 0644]
src/sim/debug.cc
src/sim/kernel_workload.cc [new file with mode: 0644]
src/sim/kernel_workload.hh [new file with mode: 0644]
src/sim/os_kernel.cc [deleted file]
src/sim/os_kernel.hh [deleted file]
src/sim/pseudo_inst.cc
src/sim/system.hh
src/sim/workload.cc [new file with mode: 0644]
src/sim/workload.hh [new file with mode: 0644]

index a424a30ce8d12f72e097019b3557a59f10d1331f..b3e248e6a44af5dc47078514e2f53ee96d5a112b 100644 (file)
@@ -388,7 +388,7 @@ def makeLinuxMipsSystem(mem_mode, mdesc=None, cmdline=None):
     self.console = binary('mips/console')
     if not cmdline:
         cmdline = 'root=/dev/hda1 console=ttyS0'
-    self.workload = OsKernel(command_line=fillInCmdline(mdesc, cmdline))
+    self.workload = KernelWorkload(command_line=fillInCmdline(mdesc, cmdline))
 
     self.system_port = self.membus.slave
 
index 459f83095a0c2382e73d43fc026c10e5d95b0ae6..bc27c6d79cb2af748c9abd656ed940f25a354d76 100644 (file)
@@ -36,7 +36,7 @@
 from m5.params import *
 from m5.options import *
 from m5.SimObject import *
-from m5.objects.OsKernel import OsKernel
+from m5.objects.Workload import KernelWorkload
 
 class ArmMachineType(Enum):
     map = {
@@ -45,7 +45,7 @@ class ArmMachineType(Enum):
         'DTOnly' : -1,
     }
 
-class ArmFsWorkload(OsKernel):
+class ArmFsWorkload(KernelWorkload):
     type = 'ArmFsWorkload'
     cxx_header = "arch/arm/fs_workload.hh"
     cxx_class = "ArmISA::FsWorkload"
index dbadb4b2a8fb9cb63069411636eca120f12f70d8..4eff04d748820d9e133208e0f0e2b5d85232c00e 100644 (file)
@@ -81,21 +81,21 @@ FsFreebsd::initState()
     // 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);
+        kernelObj->loadGlobalSymbols(kernelSymtab, 0, 0, _loadAddrMask);
+        kernelObj->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),
+    fatal_if(!kernelSymtab->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);
+            params()->atags_addr + _loadAddrOffset);
 
     DtbFile *dtb_file = new DtbFile(params()->dtb_filename);
 
@@ -108,7 +108,7 @@ FsFreebsd::initState()
         bootReleaseAddr = ra & ~ULL(0x7F);
 
     dtb_file->buildImage().
-        offset(params()->atags_addr + loadAddrOffset).
+        offset(params()->atags_addr + _loadAddrOffset).
         write(system->physProxy);
     delete dtb_file;
 
@@ -116,7 +116,7 @@ FsFreebsd::initState()
     for (auto tc: system->threadContexts) {
         tc->setIntReg(0, 0);
         tc->setIntReg(1, params()->machine_type);
-        tc->setIntReg(2, params()->atags_addr + loadAddrOffset);
+        tc->setIntReg(2, params()->atags_addr + _loadAddrOffset);
     }
 }
 
index 8f40293ebfd9d03683c82361b9975589a594002e..50a3213d5d084ef2c9a257f8e932d5b5bc40d530 100644 (file)
@@ -69,9 +69,8 @@ SkipFunc::returnFromFuncIn(ThreadContext *tc)
     }
 }
 
-FsWorkload::FsWorkload(Params *p)
-  : OsKernel(*p),
-    kernelEntry((entry & loadAddrMask) + loadAddrOffset)
+FsWorkload::FsWorkload(Params *p) : KernelWorkload(*p),
+    kernelEntry((kernelObj->entryPoint() & loadAddrMask()) + loadAddrOffset())
 {
     bootLoaders.reserve(p->boot_loader.size());
     for (const auto &bl : p->boot_loader) {
@@ -82,29 +81,19 @@ FsWorkload::FsWorkload(Params *p)
         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();
-    }
+    bootldr = getBootLoader(kernelObj);
 
     fatal_if(!bootLoaders.empty() && !bootldr,
              "Can't find a matching boot loader / kernel combination!");
 
-    if (bootldr) {
+    if (bootldr)
         bootldr->loadGlobalSymbols(debugSymbolTable);
-
-        _highestELIs64 = (bootldr->getArch() == ObjectFile::Arm64);
-    } else if (obj) {
-        _highestELIs64 = (obj->getArch() == ObjectFile::Arm64);
-    }
 }
 
 void
 FsWorkload::initState()
 {
-    OsKernel::initState();
+    KernelWorkload::initState();
 
     // Reset CP15?? What does that mean -- ali
 
@@ -144,31 +133,25 @@ FsWorkload::initState()
     } else {
         // Set the initial PC to be at start of the kernel code
         if (!arm_sys->highestELIs64())
-            arm_sys->threadContexts[0]->pcState(entry);
+            arm_sys->threadContexts[0]->pcState(kernelObj->entryPoint());
     }
 }
 
 ObjectFile *
 FsWorkload::getBootLoader(ObjectFile *const obj)
 {
-    for (auto &bl : bootLoaders) {
-        if (bl->getArch() == obj->getArch())
-            return bl.get();
+    if (obj) {
+        for (auto &bl : bootLoaders) {
+            if (bl->getArch() == obj->getArch())
+                return bl.get();
+        }
+    } else if (!bootLoaders.empty()) {
+        return bootLoaders[0].get();
     }
 
     return nullptr;
 }
 
-Addr
-FsWorkload::resetAddr() const
-{
-    if (bootldr) {
-        return bootldr->entryPoint();
-    } else {
-        return kernelEntry;
-    }
-}
-
 } // namespace ArmISA
 
 ArmISA::FsWorkload *
index 6e1af08ee795a081b3a777918a971a95e58b6e97..d6e375cd035a05e1fdfb674c1270942aab4996fa 100644 (file)
@@ -46,7 +46,7 @@
 
 #include "kern/linux/events.hh"
 #include "params/ArmFsWorkload.hh"
-#include "sim/os_kernel.hh"
+#include "sim/kernel_workload.hh"
 #include "sim/sim_object.hh"
 
 namespace ArmISA
@@ -59,7 +59,7 @@ class SkipFunc : public SkipFuncBase
     void returnFromFuncIn(ThreadContext *tc) override;
 };
 
-class FsWorkload : public OsKernel
+class FsWorkload : public KernelWorkload
 {
   protected:
     /** Bootloaders */
@@ -70,11 +70,6 @@ class FsWorkload : public OsKernel
      */
     ObjectFile *bootldr = nullptr;
 
-    /**
-     * Whether the highest exception level in software is 64 it.
-     */
-    bool _highestELIs64 = true;
-
     /**
      * This differs from entry since it takes into account where
      * the kernel is loaded in memory (with loadAddrMask and
@@ -99,19 +94,29 @@ class FsWorkload : public OsKernel
         return dynamic_cast<const Params *>(&_params);
     }
 
-    FsWorkload(Params *p);
+    Addr
+    getEntry() const override
+    {
+        if (bootldr)
+            return bootldr->entryPoint();
+        else
+            return kernelEntry;
+    }
 
-    void initState() override;
+    ObjectFile::Arch
+    getArch() const override
+    {
+        if (bootldr)
+            return bootldr->getArch();
+        else if (kernelObj)
+            return kernelObj->getArch();
+        else
+            return ObjectFile::Arm64;
+    }
 
-    /**
-     * Returns the reset address to be used by an ArmSystem.
-     * It the workload is using a bootloader, it will return
-     * the bootloader entry point.
-     * @returns Arm reset address
-     */
-    Addr resetAddr() const;
+    FsWorkload(Params *p);
 
-    bool highestELIs64() const { return _highestELIs64; }
+    void initState() override;
 };
 
 } // namespace ArmISA
index fe023cc4e1e08423bee8f7f46dc8b631397cda1b..65f0675981a5a4402c4e0d8c9b3a2030bf9ebcf2 100644 (file)
@@ -76,8 +76,8 @@ FsLinux::initState()
     // 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);
+        kernelObj->loadGlobalSymbols(kernelSymtab, 0, 0, _loadAddrMask);
+        kernelObj->loadGlobalSymbols(debugSymbolTable, 0, 0, _loadAddrMask);
     }
 
     // Setup boot data structure
@@ -85,14 +85,14 @@ FsLinux::initState()
     // 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);
+        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);
+                params()->atags_addr + _loadAddrOffset);
 
         DtbFile *dtb_file = new DtbFile(params()->dtb_filename);
 
@@ -103,7 +103,7 @@ FsLinux::initState()
         }
 
         dtb_file->buildImage().
-            offset(params()->atags_addr + loadAddrOffset).
+            offset(params()->atags_addr + _loadAddrOffset).
             write(system->physProxy);
         delete dtb_file;
     } else {
@@ -152,7 +152,7 @@ FsLinux::initState()
         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,
+        system->physProxy.writeBlob(params()->atags_addr + _loadAddrOffset,
                                     boot_data, size << 2);
 
         delete[] boot_data;
@@ -162,7 +162,7 @@ FsLinux::initState()
     for (auto tc: system->threadContexts) {
         tc->setIntReg(0, 0);
         tc->setIntReg(1, params()->machine_type);
-        tc->setIntReg(2, params()->atags_addr + loadAddrOffset);
+        tc->setIntReg(2, params()->atags_addr + _loadAddrOffset);
     }
 }
 
@@ -183,19 +183,18 @@ FsLinux::startup()
 {
     FsWorkload::startup();
 
-    auto *arm_sys = dynamic_cast<ArmSystem *>(system);
     if (enableContextSwitchStatsDump) {
-        if (!arm_sys->highestELIs64())
-            dumpStats = addKernelFuncEvent<DumpStats>("__switch_to");
-        else
+        if (getArch() == ObjectFile::Arm64)
             dumpStats = addKernelFuncEvent<DumpStats64>("__switch_to");
+        else
+            dumpStats = addKernelFuncEvent<DumpStats>("__switch_to");
 
         panic_if(!dumpStats, "dumpStats not created!");
 
         std::string task_filename = "tasks.txt";
         taskFile = simout.create(name() + "." + task_filename);
 
-        for (const auto tc : arm_sys->threadContexts) {
+        for (const auto tc : system->threadContexts) {
             uint32_t pid = tc->getCpuPtr()->getPid();
             if (pid != BaseCPU::invldPid) {
                 mapPid(tc, pid);
@@ -238,7 +237,7 @@ FsLinux::startup()
             "__const_udelay", "__const_udelay", 1000, 107374);
     }
 
-    if (highestELIs64()) {
+    if (getArch() == ObjectFile::Arm64) {
         debugPrintk = addKernelFuncEvent<
             DebugPrintk<SkipFuncLinux64>>("dprintk");
     } else {
index b5a9976cf8c32a4b7fdb68561a9274acddc0fc23..df3f6a21a48af5fb41edffe99b871c980ab48145 100644 (file)
@@ -45,7 +45,7 @@ static int32_t
 readSymbol(ThreadContext *tc, const std::string name)
 {
     PortProxy &vp = tc->getVirtProxy();
-    SymbolTable *symtab = tc->getSystemPtr()->workload->symtab;
+    const SymbolTable *symtab = tc->getSystemPtr()->workload->symtab(tc);
 
     Addr addr;
     if (!symtab->findAddress(name, addr))
index b03f0f5ae49a9969719cc8d539dc7b4486b1ae71..dd3b9a557644f6bfa0a3239de1a7ee19ecbcf20b 100644 (file)
@@ -73,25 +73,21 @@ ArmSystem::ArmSystem(Params *p)
       semihosting(p->semihosting),
       multiProc(p->multi_proc)
 {
-    auto *arm_workload = dynamic_cast<ArmISA::FsWorkload *>(p->workload);
-    panic_if(!arm_workload,
-            "Workload was not the expected type (ArmISA::FsWorkload).");
-
     if (p->auto_reset_addr) {
-        _resetAddr = arm_workload->resetAddr();
+        _resetAddr = workload->getEntry();
     } else {
         _resetAddr = p->reset_addr;
-        warn_if(arm_workload->resetAddr() != _resetAddr,
+        warn_if(workload->getEntry() != _resetAddr,
                 "Workload entry point %#x and reset address %#x are different",
-                arm_workload->resetAddr(), _resetAddr);
+                workload->getEntry(), _resetAddr);
     }
 
-    if (arm_workload->highestELIs64() != _highestELIs64) {
+    bool wl_is_64 = (workload->getArch() == ObjectFile::Arm64);
+    if (wl_is_64 != _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();
+              _highestELIs64 ? 64 : 32, wl_is_64 ? 64 : 32);
+        _highestELIs64 = wl_is_64;
     }
 
     if (_highestELIs64 && (
index 971211371672a6b966632760b83e9aa307403744..83e41b97a0a3d7286db3d3c1c57a944104e0709b 100644 (file)
@@ -47,7 +47,7 @@ class ThreadInfo
     get_data(const char *symbol, T &data)
     {
         Addr addr = 0;
-        if (!sys->workload->symtab->findAddress(symbol, addr)) {
+        if (!sys->workload->symtab(tc)->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 5d1db987ef72c7f4f671a90f86a29e8da21b87b1..93e8fcea31a35c104f3fa5501367ee872086a3c1 100644 (file)
@@ -30,9 +30,9 @@
 from m5.params import *
 
 from m5.objects.System import System
-from m5.objects.OsKernel import OsKernel
+from m5.objects.Workload import Workload
 
-class RiscvFsWorkload(OsKernel):
+class RiscvFsWorkload(Workload):
     type = 'RiscvFsWorkload'
     cxx_class = 'RiscvISA::FsWorkload'
     cxx_header = 'arch/riscv/fs_workload.hh'
index 5c031282c2bc9fa75df031a9206bf5c5664d6d6d..41fefe9339fad2d380fb86cec54668cbed11ae60 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "arch/riscv/bare_metal/fs_workload.hh"
 
+#include "arch/riscv/faults.hh"
 #include "base/loader/object_file.hh"
 #include "sim/system.hh"
 
@@ -51,6 +52,12 @@ void
 BareMetal::initState()
 {
     RiscvISA::FsWorkload::initState();
+
+    for (auto *tc: system->threadContexts) {
+        RiscvISA::Reset().invoke(tc);
+        tc->activate();
+    }
+
     warn_if(!bootloader->buildImage().write(system->physProxy),
             "Could not load sections to memory.");
 }
index 722806d22b2be26cd0c5ef0ec423209ec52d09de..37bffcfe975cf7af07b82fc3fe0309cdd56458d2 100644 (file)
@@ -47,6 +47,22 @@ class BareMetal : public RiscvISA::FsWorkload
     ~BareMetal();
 
     void initState() override;
+
+    ObjectFile::Arch
+    getArch() const override
+    {
+        return bootloader->getArch();
+    }
+    const SymbolTable *
+    symtab(ThreadContext *tc) override
+    {
+        return bootloaderSymtab;
+    }
+    bool
+    insertSymbol(Addr address, const std::string &symbol) override
+    {
+        return bootloaderSymtab->insert(address, symbol);
+    }
 };
 
 } // namespace RiscvISA
diff --git a/src/arch/riscv/bare_metal/system.cc b/src/arch/riscv/bare_metal/system.cc
deleted file mode 100644 (file)
index 1ca8ed9..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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/system.hh"
-
-#include "arch/riscv/faults.hh"
-#include "base/loader/object_file.hh"
-
-BareMetalRiscvSystem::BareMetalRiscvSystem(Params *p)
-    : RiscvSystem(p),
-      bootloader(createObjectFile(p->bootloader))
-{
-    if (bootloader == NULL) {
-         fatal("Could not load bootloader file %s", p->bootloader);
-    }
-
-    _resetVect = bootloader->entryPoint();
-}
-
-BareMetalRiscvSystem::~BareMetalRiscvSystem()
-{
-    delete bootloader;
-}
-
-void
-BareMetalRiscvSystem::initState()
-{
-    // Call the initialisation of the super class
-    RiscvSystem::initState();
-
-    for (auto *tc: threadContexts) {
-        RiscvISA::Reset().invoke(tc);
-        tc->activate();
-    }
-
-    // load program sections into memory
-    if (!bootloader->buildImage().write(physProxy)) {
-        warn("could not load sections to memory");
-    }
-}
-
-BareMetalRiscvSystem *
-BareMetalRiscvSystemParams::create()
-{
-    return new BareMetalRiscvSystem(this);
-}
-
diff --git a/src/arch/riscv/bare_metal/system.hh b/src/arch/riscv/bare_metal/system.hh
deleted file mode 100644 (file)
index 1f665be..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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/system.hh"
-#include "params/BareMetalRiscvSystem.hh"
-
-class BareMetalRiscvSystem : public RiscvSystem
-{
-  protected:
-    ObjectFile* bootloader;
-
-  public:
-    typedef BareMetalRiscvSystemParams Params;
-    BareMetalRiscvSystem(Params *p);
-    ~BareMetalRiscvSystem();
-
-    // initialize the system
-    virtual void initState();
-};
-
-#endif // __ARCH_RISCV_BARE_METAL_SYSTEM_HH__
-
index aaa9d0f58923bd67a3427533509c16e6f1b17914..0fbd7170dc55a86bd5a31967147cdd3f7c8c7eb0 100644 (file)
 #define __ARCH_RISCV_FS_WORKLOAD_HH__
 
 #include "params/RiscvFsWorkload.hh"
-#include "sim/os_kernel.hh"
 #include "sim/sim_object.hh"
+#include "sim/workload.hh"
 
 namespace RiscvISA
 {
 
-class FsWorkload : public OsKernel
+class FsWorkload : public Workload
 {
   protected:
     // checker for bare metal application
@@ -46,7 +46,7 @@ class FsWorkload : public OsKernel
     Addr _resetVect;
 
   public:
-    FsWorkload(RiscvFsWorkloadParams *p) : OsKernel(*p),
+    FsWorkload(RiscvFsWorkloadParams *p) : Workload(p),
         _isBareMetal(p->bare_metal), _resetVect(p->reset_vect)
     {}
 
@@ -55,6 +55,8 @@ class FsWorkload : public OsKernel
 
     // return bare metal checker
     bool isBareMetal() const { return _isBareMetal; }
+
+    Addr getEntry() const override { return _resetVect; }
 };
 
 } // namespace RiscvISA
index 6244882b9c3bbb091b30fdbadc7a15da891c48ee..ffc3f2b2cee86dde4fd2fe44c0e96864b9f1e0a1 100644 (file)
 
 from m5.params import *
 
-from m5.objects.OsKernel import OsKernel
+from m5.objects.Workload import Workload
 
-class SparcFsWorkload(OsKernel):
+class SparcFsWorkload(Workload):
     type = 'SparcFsWorkload'
     cxx_header = 'arch/sparc/fs_workload.hh'
     cxx_class = 'SparcISA::FsWorkload'
-
-    load_addr_mask = 0xffffffffff
index e0fa8e41ac5ef8d23b56809f0357b07c0aebe9d5..71c3b45146c1f24e41dbf330512918e03c74c137 100644 (file)
@@ -38,7 +38,7 @@ namespace SparcISA
 void
 FsWorkload::initState()
 {
-    OsKernel::initState();
+    Workload::initState();
 
     if (system->threadContexts.empty())
         return;
index 2ffc06a64f88648490c7d1a426ac27d78248ae35..d97b9225bd06910150ff9d4f0e8f1366138618d3 100644 (file)
 #ifndef __ARCH_SPARC_FS_WORKLOAD_HH__
 #define __ARCH_SPARC_FS_WORKLOAD_HH__
 
+#include "arch/sparc/faults.hh"
 #include "params/SparcFsWorkload.hh"
-#include "sim/os_kernel.hh"
+#include "sim/workload.hh"
 
 namespace SparcISA
 {
 
-class FsWorkload : public OsKernel
+class FsWorkload : public Workload
 {
+  protected:
+    SymbolTable defaultSymtab;
+
   public:
-    FsWorkload(SparcFsWorkloadParams *p) : OsKernel(*p) {}
+    FsWorkload(SparcFsWorkloadParams *params) : Workload(params) {}
     void initState() override;
+
+    Addr
+    getEntry() const override
+    {
+        Addr pc, npc;
+        getREDVector(0x001, pc, npc);
+        return pc;
+    }
+    ObjectFile::Arch getArch() const override { return ObjectFile::SPARC64; }
+
+    const SymbolTable *
+    symtab(ThreadContext *tc) override
+    {
+        return &defaultSymtab;
+    }
+
+    bool
+    insertSymbol(Addr address, const std::string &symbol) override
+    {
+        return defaultSymtab.insert(address, symbol);
+    }
 };
 
 } // namespace SparcISA
index 3628c941ec84b1bb48ffb058717e3afdcee4bc20..1a4248f6e824c72f475e212f2c9a3f0d70fe7d85 100644 (file)
@@ -39,9 +39,9 @@ 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
+from m5.objects.Workload import KernelWorkload
 
-class X86FsWorkload(OsKernel):
+class X86FsWorkload(KernelWorkload):
     type = 'X86FsWorkload'
     cxx_header = 'arch/x86/fs_workload.hh'
     cxx_class = 'X86ISA::FsWorkload'
index c38fc9b51ba0058fb032aa504c5c501fbf3df591..6ad42db0469627a5b9437bcf982ae2aba0d54e8c 100644 (file)
@@ -50,7 +50,7 @@
 namespace X86ISA
 {
 
-FsWorkload::FsWorkload(Params *p) : OsKernel(*p),
+FsWorkload::FsWorkload(Params *p) : KernelWorkload(*p),
     smbiosTable(p->smbios_table),
     mpFloatingPointer(p->intel_mp_pointer),
     mpConfigTable(p->intel_mp_table),
@@ -104,7 +104,7 @@ installSegDesc(ThreadContext *tc, SegmentRegIndex seg,
 void
 FsWorkload::initState()
 {
-    OsKernel::initState();
+    KernelWorkload::initState();
 
     for (auto *tc: system->threadContexts) {
         X86ISA::InitInterrupt(0).invoke(tc);
@@ -119,9 +119,9 @@ FsWorkload::initState()
         }
     }
 
-    fatal_if(!obj, "No kernel to load.");
+    fatal_if(!kernelObj, "No kernel to load.");
 
-    fatal_if(obj->getArch() == ObjectFile::I386,
+    fatal_if(kernelObj->getArch() == ObjectFile::I386,
              "Loading a 32 bit x86 kernel is not supported.");
 
     ThreadContext *tc = system->threadContexts[0];
@@ -304,7 +304,7 @@ FsWorkload::initState()
     cr0.pg = 1;
     tc->setMiscReg(MISCREG_CR0, cr0);
 
-    tc->pcState(entry);
+    tc->pcState(kernelObj->entryPoint());
 
     // We should now be in long mode. Yay!
 
index 5b972ec80cc13f1beed661fed37d2e2bbb652686..7080feb40638ff411c605e4b6bb8db8a0600a91e 100644 (file)
@@ -46,7 +46,7 @@
 #include "base/types.hh"
 #include "cpu/thread_context.hh"
 #include "params/X86FsWorkload.hh"
-#include "sim/os_kernel.hh"
+#include "sim/kernel_workload.hh"
 
 namespace X86ISA
 {
@@ -79,7 +79,7 @@ const Addr MMIORegionPhysAddr = 0xffff0000;
 void installSegDesc(ThreadContext *tc, SegmentRegIndex seg,
                     SegDescriptor desc, bool longmode);
 
-class FsWorkload : public OsKernel
+class FsWorkload : public KernelWorkload
 {
   public:
     typedef X86FsWorkloadParams Params;
index 64f2d4b1dede4c334f1662b834e82e7c9ee9c9b3..677ab65d5481810e8f1dc2bfd71f9ab657f60f12 100644 (file)
@@ -45,7 +45,7 @@ static int32_t
 readSymbol(ThreadContext *tc, const std::string name)
 {
     PortProxy &vp = tc->getVirtProxy();
-    SymbolTable *symtab = tc->getSystemPtr()->workload->symtab;
+    const SymbolTable *symtab = tc->getSystemPtr()->workload->symtab(tc);
 
     Addr addr;
     if (!symtab->findAddress(name, addr))
@@ -189,7 +189,7 @@ void
 StackTrace::dump()
 {
     StringWrap name(tc->getCpuPtr()->name());
-    SymbolTable *symtab = tc->getSystemPtr()->workload->symtab;
+    const SymbolTable *symtab = tc->getSystemPtr()->workload->symtab(tc);
 
     DPRINTFN("------ Stack ------\n");
 
index b1814dbc6e9a73b23e3585c2a19bc6f94cf08b2f..030dc4ba266e7600603d7ababfb240db13bdb806 100644 (file)
@@ -104,7 +104,7 @@ struct O3ThreadState : public ThreadState {
 
         if (cpu->params()->profile) {
             profile = new FunctionProfile(
-                    cpu->params()->system->workload->symtab);
+                    cpu->params()->system->workload->symtab(tc));
             Callback *cb =
                 new MakeCallback<O3ThreadState,
                 &O3ThreadState::dumpFuncProfile>(this);
index 9e2e55e8e4bd91193be68ab87e33261bdc2c63af..ef8e074e0b1cbb998019c3edceb95cd384a5fab2 100644 (file)
@@ -98,7 +98,7 @@ SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
     clearArchRegs();
 
     if (baseCpu->params()->profile) {
-        profile = new FunctionProfile(system->workload->symtab);
+        profile = new FunctionProfile(system->workload->symtab(this));
         Callback *cb =
             new MakeCallback<SimpleThread,
             &SimpleThread::dumpFuncProfile>(this);
index 5598440044c70bc7605d52bf6c79ae5e636c971e..548ae0fe052a208821b4d26de9bc14852797b080 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->workload->symtab;
+    const SymbolTable *symtab = system->workload->symtab(tc);
     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
deleted file mode 100644 (file)
index 93cb74f..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-# 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 9687796ab8de203e4460b1aea042c68df33751c2..0057d28cf106120bf96184d09446040abbd72364 100644 (file)
@@ -30,7 +30,7 @@ Import('*')
 
 SimObject('ClockedObject.py')
 SimObject('TickedObject.py')
-SimObject('OsKernel.py')
+SimObject('Workload.py')
 SimObject('Root.py')
 SimObject('ClockDomain.py')
 SimObject('VoltageDomain.py')
@@ -53,7 +53,8 @@ Source('global_event.cc')
 Source('init.cc', add_tags='python')
 Source('init_signals.cc')
 Source('main.cc', tags='main')
-Source('os_kernel.cc')
+Source('workload.cc')
+Source('kernel_workload.cc')
 Source('port.cc')
 Source('python.cc', add_tags='python')
 Source('redirect_path.cc')
index 0d1f73055f1d04ac1b7444b3d6a073f79004074f..61fbe0e020393456c01e67f0f95acb7fbe0e83a3 100644 (file)
@@ -99,7 +99,7 @@ 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")
+    workload = Param.Workload(NULL, "Operating system kernel")
     init_param = Param.UInt64(0, "numerical value to pass into simulator")
     readfile = Param.String("", "file to read startup script from")
     symbolfile = Param.String("", "file to get the symbols from")
diff --git a/src/sim/Workload.py b/src/sim/Workload.py
new file mode 100644 (file)
index 0000000..1e35abe
--- /dev/null
@@ -0,0 +1,52 @@
+# 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 Workload(SimObject):
+    type = 'Workload'
+    cxx_header = "sim/workload.hh"
+    abstract = True
+
+class KernelWorkload(Workload):
+    type = 'KernelWorkload'
+    cxx_header = "sim/kernel_workload.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 bf46a51b26a270e4c6fa5dcb20584ec255fc4b6c..484d4a6702b2ec40bc6419a25ff2f35ad10e35b9 100644 (file)
@@ -35,6 +35,7 @@
 #include "cpu/pc_event.hh"
 #include "sim/eventq_impl.hh"
 #include "sim/global_event.hh"
+#include "sim/kernel_workload.hh"
 #include "sim/sim_events.hh"
 #include "sim/sim_exit.hh"
 #include "sim/system.hh"
diff --git a/src/sim/kernel_workload.cc b/src/sim/kernel_workload.cc
new file mode 100644 (file)
index 0000000..3d9a5dc
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * 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/kernel_workload.hh"
+
+#include "debug/Loader.hh"
+#include "params/KernelWorkload.hh"
+#include "sim/system.hh"
+
+KernelWorkload::KernelWorkload(const Params &p) : Workload(&p), _params(p),
+    _loadAddrMask(p.load_addr_mask), _loadAddrOffset(p.load_addr_offset),
+    kernelSymtab(new SymbolTable), commandLine(p.command_line)
+{
+    if (!debugSymbolTable)
+        debugSymbolTable = new SymbolTable;
+
+    kernelObj = createObjectFile(params().object_file);
+    inform("kernel located at: %s", params().object_file);
+
+    fatal_if(!kernelObj,
+            "Could not load kernel file %s", params().object_file);
+
+    image = kernelObj->buildImage();
+
+    _start = image.minAddr();
+    _end = image.maxAddr();
+
+    // 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(!kernelObj->loadGlobalSymbols(kernelSymtab),
+            "Could not load kernel symbols.");
+
+    fatal_if(!kernelObj->loadLocalSymbols(kernelSymtab),
+            "Could not load kernel local symbols.");
+
+    fatal_if(!kernelObj->loadGlobalSymbols(debugSymbolTable),
+            "Could not load kernel symbols.");
+
+    fatal_if(!kernelObj->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);
+    }
+}
+
+KernelWorkload::~KernelWorkload()
+{
+    delete kernelSymtab;
+}
+
+void
+KernelWorkload::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", kernelObj->entryPoint());
+        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
+KernelWorkload::serialize(CheckpointOut &cp) const
+{
+    kernelSymtab->serialize("symtab", cp);
+}
+
+void
+KernelWorkload::unserialize(CheckpointIn &cp)
+{
+    kernelSymtab->unserialize("symtab", cp);
+}
+
+KernelWorkload *
+KernelWorkloadParams::create()
+{
+    return new KernelWorkload(*this);
+}
diff --git a/src/sim/kernel_workload.hh b/src/sim/kernel_workload.hh
new file mode 100644 (file)
index 0000000..b45a0d9
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * 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_KERNEL_WORKLOAD_HH__
+#define __SIM_KERNEL_WORKLOAD_HH__
+
+#include <string>
+#include <vector>
+
+#include "base/loader/object_file.hh"
+#include "base/types.hh"
+#include "params/KernelWorkload.hh"
+#include "sim/workload.hh"
+
+class SymbolTable;
+class System;
+
+class KernelWorkload : public Workload
+{
+  public:
+    using Params = KernelWorkloadParams;
+
+  protected:
+    const Params &_params;
+
+    MemoryImage image;
+
+    /** 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;
+
+    Addr _start, _end;
+
+    std::vector<ObjectFile *> extras;
+
+    ObjectFile *kernelObj = nullptr;
+    SymbolTable *kernelSymtab = nullptr;
+
+    const std::string commandLine;
+
+  public:
+    const Params &params() const { return _params; }
+
+    Addr start() const { return _start; }
+    Addr end() const { return _end; }
+    Addr loadAddrMask() const { return _loadAddrMask; }
+    Addr loadAddrOffset() const { return _loadAddrOffset; }
+
+    KernelWorkload(const Params &p);
+    ~KernelWorkload();
+
+    Addr getEntry() const override { return kernelObj->entryPoint(); }
+    ObjectFile::Arch getArch() const override { return kernelObj->getArch(); }
+    const SymbolTable *
+    symtab(ThreadContext *tc) override
+    {
+        return kernelSymtab;
+    }
+
+    bool
+    insertSymbol(Addr address, const std::string &symbol)
+    {
+        return kernelSymtab->insert(address, symbol);
+    }
+
+    void initState() override;
+
+    void serialize(CheckpointOut &cp) const override;
+    void unserialize(CheckpointIn &cp) override;
+
+    /** @{ */
+    /**
+     * 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)...);
+        panic_if(!e, "Failed to find kernel symbol '%s'", lbl);
+        return e;
+    }
+    /** @} */
+};
+
+#endif // __SIM_KERNEL_WORKLOAD_HH__
diff --git a/src/sim/os_kernel.cc b/src/sim/os_kernel.cc
deleted file mode 100644 (file)
index 317f4d3..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index b1238a1..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * 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 e30738720ef214bfc34a0e3ee20894fa8b7980c1..802b30423984b3c25e43523c4925da9bf0729d83 100644 (file)
@@ -217,7 +217,7 @@ loadsymbol(ThreadContext *tc)
         if (!to_number(address, addr))
             continue;
 
-        if (!tc->getSystemPtr()->workload->symtab->insert(addr, symbol))
+        if (!tc->getSystemPtr()->workload->insertSymbol(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()->workload->symtab->insert(addr,symbol);
+    tc->getSystemPtr()->workload->insertSymbol(addr, symbol);
     debugSymbolTable->insert(addr,symbol);
 }
 
index f9a437becc267e1f8799469bbca875f644f29af5..09ba7b430886f3933e6872b3723245096fcd05a5 100644 (file)
 #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"
+#include "sim/workload.hh"
 
 class BaseRemoteGDB;
 class KvmVM;
@@ -211,7 +211,7 @@ class System : public SimObject, public PCEventScope
     PortProxy physProxy;
 
     /** OS kernel */
-    OsKernel *workload = nullptr;
+    Workload *workload = nullptr;
 
   public:
     /**
diff --git a/src/sim/workload.cc b/src/sim/workload.cc
new file mode 100644 (file)
index 0000000..06773f9
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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/workload.hh"
+
+#include "params/Workload.hh"
+#include "sim/system.hh"
+
+Addr
+Workload::fixFuncEventAddr(Addr addr)
+{
+    return system->fixFuncEventAddr(addr);
+}
diff --git a/src/sim/workload.hh b/src/sim/workload.hh
new file mode 100644 (file)
index 0000000..2dbcaa0
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * 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_WORKLOAD_HH__
+#define __SIM_WORKLOAD_HH__
+
+#include "base/loader/object_file.hh"
+#include "base/loader/symtab.hh"
+#include "params/Workload.hh"
+#include "sim/sim_object.hh"
+
+class System;
+class ThreadContext;
+
+class Workload : public SimObject
+{
+  protected:
+    Addr fixFuncEventAddr(Addr);
+
+  public:
+    using SimObject::SimObject;
+
+    System *system = nullptr;
+
+    virtual Addr getEntry() const = 0;
+    virtual ObjectFile::Arch getArch() const = 0;
+
+    virtual const SymbolTable *symtab(ThreadContext *tc) = 0;
+    virtual bool insertSymbol(Addr address, const std::string &symbol) = 0;
+
+    /** @{ */
+    /**
+     * 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;
+    }
+    /** @} */
+};
+
+#endif // __SIM_WORKLOAD_HH__