/*
 * Copyright (c) 2004-2005 The Regents of The University of Michigan
 * Copyright (c) 2016 The University of Virginia
 * 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.
 *
 * Authors: Gabe Black
 *          Ali Saidi
 *          Korey Sewell
 *          Alec Roelke
 */
#include "arch/riscv/process.hh"

#include <algorithm>
#include <cstddef>
#include <iostream>
#include <iterator>
#include <map>
#include <string>
#include <vector>

#include "arch/riscv/isa.hh"
#include "arch/riscv/isa_traits.hh"
#include "arch/riscv/registers.hh"
#include "base/loader/elf_object.hh"
#include "base/loader/object_file.hh"
#include "base/logging.hh"
#include "base/random.hh"
#include "cpu/thread_context.hh"
#include "debug/Stack.hh"
#include "mem/page_table.hh"
#include "params/Process.hh"
#include "sim/aux_vector.hh"
#include "sim/process.hh"
#include "sim/process_impl.hh"
#include "sim/syscall_return.hh"
#include "sim/system.hh"

using namespace std;
using namespace RiscvISA;

RiscvProcess::RiscvProcess(ProcessParams *params, ObjectFile *objFile) :
        Process(params,
                new EmulationPageTable(params->name, params->pid, PageBytes),
                objFile)
{
    fatal_if(params->useArchPT, "Arch page tables not implemented.");
    const Addr stack_base = 0x7FFFFFFFFFFFFFFFL;
    const Addr max_stack_size = 8 * 1024 * 1024;
    const Addr next_thread_stack_base = stack_base - max_stack_size;
    const Addr brk_point = roundUp(objFile->bssBase() + objFile->bssSize(),
            PageBytes);
    const Addr mmap_end = 0x4000000000000000L;
    memState = make_shared<MemState>(brk_point, stack_base, max_stack_size,
            next_thread_stack_base, mmap_end);
}

void
RiscvProcess::initState()
{
    Process::initState();

    argsInit<uint64_t>(PageBytes);
    for (ContextID ctx: contextIds)
        system->getThreadContext(ctx)->setMiscRegNoEffect(MISCREG_PRV, PRV_U);
}

template<class IntType> void
RiscvProcess::argsInit(int pageSize)
{
    const int RandomBytes = 16;

    updateBias();
    objFile->loadSections(initVirtMem);
    ElfObject* elfObject = dynamic_cast<ElfObject*>(objFile);
    memState->setStackMin(memState->getStackBase());

    // Determine stack size and populate auxv
    Addr stack_top = memState->getStackMin();
    stack_top -= RandomBytes;
    for (const string& arg: argv)
        stack_top -= arg.size() + 1;
    for (const string& env: envp)
        stack_top -= env.size() + 1;
    stack_top &= -sizeof(Addr);

    vector<AuxVector<IntType>> auxv;
    if (elfObject != nullptr) {
        auxv.push_back({M5_AT_ENTRY, objFile->entryPoint()});
        auxv.push_back({M5_AT_PHNUM, elfObject->programHeaderCount()});
        auxv.push_back({M5_AT_PHENT, elfObject->programHeaderSize()});
        auxv.push_back({M5_AT_PHDR, elfObject->programHeaderTable()});
        auxv.push_back({M5_AT_PAGESZ, PageBytes});
        auxv.push_back({M5_AT_SECURE, 0});
        auxv.push_back({M5_AT_RANDOM, stack_top});
        auxv.push_back({M5_AT_NULL, 0});
    }
    stack_top -= (1 + argv.size()) * sizeof(Addr) +
                   (1 + envp.size()) * sizeof(Addr) +
                   sizeof(Addr) + 2 * sizeof(IntType) * auxv.size();
    stack_top &= -2*sizeof(Addr);
    memState->setStackSize(memState->getStackBase() - stack_top);
    allocateMem(roundDown(stack_top, pageSize),
            roundUp(memState->getStackSize(), pageSize));

    // Copy random bytes (for AT_RANDOM) to stack
    memState->setStackMin(memState->getStackMin() - RandomBytes);
    uint8_t at_random[RandomBytes];
    generate(begin(at_random), end(at_random),
             [&]{ return random_mt.random(0, 0xFF); });
    initVirtMem.writeBlob(memState->getStackMin(), at_random, RandomBytes);

    // Copy argv to stack
    vector<Addr> argPointers;
    for (const string& arg: argv) {
        memState->setStackMin(memState->getStackMin() - (arg.size() + 1));
        initVirtMem.writeString(memState->getStackMin(), arg.c_str());
        argPointers.push_back(memState->getStackMin());
        if (DTRACE(Stack)) {
            string wrote;
            initVirtMem.readString(wrote, argPointers.back());
            DPRINTFN("Wrote arg \"%s\" to address %p\n",
                    wrote, (void*)memState->getStackMin());
        }
    }
    argPointers.push_back(0);

    // Copy envp to stack
    vector<Addr> envPointers;
    for (const string& env: envp) {
        memState->setStackMin(memState->getStackMin() - (env.size() + 1));
        initVirtMem.writeString(memState->getStackMin(), env.c_str());
        envPointers.push_back(memState->getStackMin());
        DPRINTF(Stack, "Wrote env \"%s\" to address %p\n",
                env, (void*)memState->getStackMin());
    }
    envPointers.push_back(0);

    // Align stack
    memState->setStackMin(memState->getStackMin() & -sizeof(Addr));

    // Calculate bottom of stack
    memState->setStackMin(memState->getStackMin() -
            ((1 + argv.size()) * sizeof(Addr) +
             (1 + envp.size()) * sizeof(Addr) +
             sizeof(Addr) + 2 * sizeof(IntType) * auxv.size()));
    memState->setStackMin(memState->getStackMin() & -2*sizeof(Addr));
    Addr sp = memState->getStackMin();
    const auto pushOntoStack =
        [this, &sp](const uint8_t* data, const size_t size) {
            initVirtMem.writeBlob(sp, data, size);
            sp += size;
        };

    // Push argc and argv pointers onto stack
    IntType argc = htog((IntType)argv.size());
    DPRINTF(Stack, "Wrote argc %d to address %p\n",
            argv.size(), (void*)sp);
    pushOntoStack((uint8_t*)&argc, sizeof(IntType));
    for (const Addr& argPointer: argPointers) {
        DPRINTF(Stack, "Wrote argv pointer %p to address %p\n",
                (void*)argPointer, (void*)sp);
        pushOntoStack((uint8_t*)&argPointer, sizeof(Addr));
    }

    // Push env pointers onto stack
    for (const Addr& envPointer: envPointers) {
        DPRINTF(Stack, "Wrote envp pointer %p to address %p\n",
                (void*)envPointer, (void*)sp);
        pushOntoStack((uint8_t*)&envPointer, sizeof(Addr));
    }

    // Push aux vector onto stack
    std::map<IntType, string> aux_keys = {
        {M5_AT_ENTRY, "M5_AT_ENTRY"},
        {M5_AT_PHNUM, "M5_AT_PHNUM"},
        {M5_AT_PHENT, "M5_AT_PHENT"},
        {M5_AT_PHDR, "M5_AT_PHDR"},
        {M5_AT_PAGESZ, "M5_AT_PAGESZ"},
        {M5_AT_SECURE, "M5_AT_SECURE"},
        {M5_AT_RANDOM, "M5_AT_RANDOM"},
        {M5_AT_NULL, "M5_AT_NULL"}
    };
    for (const AuxVector<IntType>& aux: auxv) {
        DPRINTF(Stack, "Wrote aux key %s to address %p\n",
                aux_keys[aux.a_type], (void*)sp);
        pushOntoStack((uint8_t*)&aux.a_type, sizeof(IntType));
        DPRINTF(Stack, "Wrote aux value %x to address %p\n",
                aux.a_val, (void*)sp);
        pushOntoStack((uint8_t*)&aux.a_val, sizeof(IntType));
    }

    ThreadContext *tc = system->getThreadContext(contextIds[0]);
    tc->setIntReg(StackPointerReg, memState->getStackMin());
    tc->pcState(getStartPC());

    memState->setStackMin(roundDown(memState->getStackMin(), pageSize));
}

RiscvISA::IntReg
RiscvProcess::getSyscallArg(ThreadContext *tc, int &i)
{
    // If a larger index is requested than there are syscall argument
    // registers, return 0
    RiscvISA::IntReg retval = 0;
    if (i < SyscallArgumentRegs.size())
        retval = tc->readIntReg(SyscallArgumentRegs[i]);
    i++;
    return retval;
}

void
RiscvProcess::setSyscallArg(ThreadContext *tc, int i, RiscvISA::IntReg val)
{
    tc->setIntReg(SyscallArgumentRegs[i], val);
}

void
RiscvProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
{
    if (sysret.successful()) {
        // no error
        tc->setIntReg(SyscallPseudoReturnReg, sysret.returnValue());
    } else {
        // got an error, return details
        tc->setIntReg(SyscallPseudoReturnReg, sysret.errnoValue());
    }
}
