/*
 * 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"

namespace gem5
{

KernelWorkload::KernelWorkload(const Params &p) : Workload(p),
    _loadAddrMask(p.load_addr_mask), _loadAddrOffset(p.load_addr_offset),
    commandLine(p.command_line)
{
    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;
        });

        kernelSymtab = kernelObj->symtab();
        auto initKernelSymtab = kernelSymtab.mask(_loadAddrMask)
            ->offset(_loadAddrOffset)
            ->rename([](std::string &name) {
                name = "kernel_init." + name;
            });

        loader::debugSymbolTable.insert(*initKernelSymtab);
        loader::debugSymbolTable.insert(kernelSymtab);
    }

    // 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);
    }
}

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);
}

} // namespace gem5
