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

KernelWorkload *
KernelWorkloadParams::create()
{
    return new KernelWorkload(*this);
}
