/*
 * Copyright (c) 2012-2013, 2015 ARM Limited
 * Copyright (c) 2015-2016 Advanced Micro Devices, Inc.
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * 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.
 */

#ifndef __SIM_SYSCALL_DESC_HH__
#define __SIM_SYSCALL_DESC_HH__

#include <functional>
#include <map>
#include <string>

#include "base/logging.hh"
#include "base/types.hh"
#include "cpu/thread_context.hh"
#include "sim/guest_abi.hh"
#include "sim/process.hh"
#include "sim/syscall_return.hh"

class SyscallDesc;

SyscallReturn unimplementedFunc(SyscallDesc *desc, ThreadContext *tc);

/**
 * This class provides the wrapper interface for the system call
 * implementations which are defined in the sim/syscall_emul files and
 * bound to the ISAs in the architecture specific code
 * (i.e. arch/X86/linux/process.cc).
 */
class SyscallDesc {
  public:
    /**
     * Interface for invoking the system call funcion pointer. Note that
     * this acts as a gateway for all system calls and serves a good point
     * to add filters for behaviors or apply checks for all system calls.
     * @param tc Handle for owning ThreadContext to pass information
     */
    void doSyscall(ThreadContext *tc);

    std::string name() const { return _name; }
    int num() const { return _num; }

    /**
     * For use within the system call executor if new threads are created and
     * need something returned into them.
     */
    virtual void returnInto(ThreadContext *tc, const SyscallReturn &ret) = 0;

  protected:
    using Executor =
        std::function<SyscallReturn(SyscallDesc *, ThreadContext *)>;
    using Dumper = std::function<std::string(std::string, ThreadContext *)>;

    SyscallDesc(int num, const char *name, Executor exec, Dumper dump) :
        _name(name), _num(num), executor(exec), dumper(dump)
    {}

  private:
    /** System call name (e.g., open, mmap, clone, socket, etc.) */
    std::string _name;
    int _num;

    /** Mechanism for ISAs to connect to the emul function definitions */
    Executor executor;
    Dumper dumper;
};

/*
 * This SyscallDesc subclass template adapts a given syscall implementation so
 * that some arguments can come from the simulator (desc, num and tc) while the
 * rest can come from the guest using the GuestABI mechanism.
 */
template <typename ABI>
class SyscallDescABI : public SyscallDesc
{
  private:
    // Aliases to make the code below a little more concise.
    template <typename ...Args>
    using ABIExecutor =
        std::function<SyscallReturn(SyscallDesc *, ThreadContext *, Args...)>;

    template <typename ...Args>
    using ABIExecutorPtr =
        SyscallReturn (*)(SyscallDesc *, ThreadContext *, Args...);


    // Wrap an executor with guest arguments with a normal executor that gets
    // those additional arguments from the guest context.
    template <typename ...Args>
    static inline Executor
    buildExecutor(ABIExecutor<Args...> target)
    {
        return [target](SyscallDesc *desc,
                        ThreadContext *tc) -> SyscallReturn {
            // Create a partial function which will stick desc to the front of
            // the parameter list.
            auto partial = [target,desc](
                    ThreadContext *tc, Args... args) -> SyscallReturn {
                return target(desc, tc, args...);
            };

            // Use invokeSimcall to gather the other arguments based on the
            // given ABI and pass them to the syscall implementation.
            return invokeSimcall<ABI, SyscallReturn, Args...>(tc,
                    std::function<SyscallReturn(ThreadContext *, Args...)>(
                        partial));
        };
    }

    template <typename ...Args>
    static inline Dumper
    buildDumper()
    {
        return [](std::string name, ThreadContext *tc) -> std::string {
            return dumpSimcall<ABI, SyscallReturn, Args...>(name, tc);
        };
    }

  public:
    // Constructors which plumb in buildExecutor.
    template <typename ...Args>
    SyscallDescABI(int num, const char *name, ABIExecutor<Args...> target) :
        SyscallDesc(num, name, buildExecutor<Args...>(target),
                               buildDumper<Args...>())
    {}

    template <typename ...Args>
    SyscallDescABI(int num, const char *name, ABIExecutorPtr<Args...> target) :
        SyscallDescABI(num, name, ABIExecutor<Args...>(target))
    {}

    SyscallDescABI(int num, const char *name) :
        SyscallDescABI(num, name, ABIExecutor<>(unimplementedFunc))
    {}

    void
    returnInto(ThreadContext *tc, const SyscallReturn &ret) override
    {
        GuestABI::Result<ABI, SyscallReturn>::store(tc, ret);
    }
};

template <typename ABI>
class SyscallDescTable
{
  private:
    std::map<int, SyscallDescABI<ABI>> _descs;

  public:
    SyscallDescTable(std::initializer_list<SyscallDescABI<ABI>> descs)
    {
        for (auto &desc: descs) {
            auto res = _descs.insert({desc.num(), desc});
            panic_if(!res.second, "Failed to insert desc %s", desc.name());
        }
    }

    SyscallDesc
    *get(int num, bool fatal_if_missing=true)
    {
        auto it = _descs.find(num);
        if (it == _descs.end()) {
            if (fatal_if_missing)
                fatal("Syscall %d out of range", num);
            else
                return nullptr;
        }
        return &it->second;
    }
};

#endif // __SIM_SYSCALL_DESC_HH__
