The following patch: https://gem5-review.googlesource.com/c/public/gem5/+/24283 Removed the capability of starting a gem5 simulation without a kernel object. This patch is restoring it Change-Id: I6d751bac386cbb250b3593bb12463140dc964ab3 Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com> Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/28147 Reviewed-by: Gabe Black <gabeblack@google.com> Tested-by: kokoro <noreply+kokoro@google.com>
162 lines
5.8 KiB
C++
162 lines
5.8 KiB
C++
/*
|
|
* 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 Loader::SymbolTable), commandLine(p.command_line)
|
|
{
|
|
if (!Loader::debugSymbolTable)
|
|
Loader::debugSymbolTable = new Loader::SymbolTable;
|
|
|
|
if (params().object_file == "") {
|
|
inform("No kernel set for full system simulation. "
|
|
"Assuming you know what you're doing.");
|
|
} else {
|
|
kernelObj = Loader::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(Loader::debugSymbolTable),
|
|
"Could not load kernel symbols.");
|
|
|
|
fatal_if(!kernelObj->loadLocalSymbols(Loader::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;
|
|
auto *obj = Loader::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);
|
|
}
|