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

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