#include "sim/syscall_desc.hh"
-#include <memory>
-
-#include "base/trace.hh"
#include "base/types.hh"
-#include "config/the_isa.hh"
-#include "cpu/base.hh"
-#include "cpu/thread_context.hh"
-#include "sim/faults.hh"
-#include "sim/process.hh"
#include "sim/syscall_debug_macros.hh"
+class ThreadContext;
+
void
SyscallDesc::doSyscall(int callnum, ThreadContext *tc, Fault *fault)
{
- RegVal arg[6] M5_VAR_USED;
- auto process = tc->getProcessPtr();
-
- /**
- * Step through the first six parameters for the system call and
- * retrieve their values. Note that index is incremented as a
- * side-effect of the getSyscallArg method.
- */
- int index = 0;
- for (int i = 0; i < 6; i++)
- arg[i] = process->getSyscallArg(tc, index);
+ DPRINTF_SYSCALL(Base, "Calling %s...\n", dumper(name(), tc));
- /**
- * Linux supports up to six system call arguments through registers
- * so we want to print all six. Check to the relevant man page to
- * verify how many are actually used by a given system call.
- */
- DPRINTF_SYSCALL(Base, "%s called w/arguments %d, %d, %d, %d, %d, %d\n",
- _name, arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]);
-
- /** Invoke the system call */
SyscallReturn retval = executor(this, callnum, tc);
- /**
- * If the system call needs to be restarted, most likely due to
- * blocking behavior, warn that the system call will retry;
- * alternatively, print the return value.
- */
- if (retval.needsRetry()) {
- *fault = std::make_shared<SyscallRetryFault>();
- DPRINTF_SYSCALL(Base, "%s needs retry\n", _name);
- } else
- DPRINTF_SYSCALL(Base, "%s returns %d\n", _name, retval.encodedValue());
-
- if (!retval.suppressed() && !retval.needsRetry())
- process->setSyscallReturn(tc, retval);
+ if (retval.needsRetry())
+ DPRINTF_SYSCALL(Base, "Needs retry.\n", name());
+ else if (retval.suppressed())
+ DPRINTF_SYSCALL(Base, "No return value.\n", name());
+ else
+ DPRINTF_SYSCALL(Base, "Returned %d.\n", retval.encodedValue());
}
*/
class SyscallDesc {
public:
- using SyscallExecutor =
- std::function<SyscallReturn(SyscallDesc *, int num, ThreadContext *)>;
-
- SyscallDesc(const char *name, SyscallExecutor sys_exec=unimplementedFunc)
- : _name(name), executor(sys_exec)
- {}
-
/**
* Interface for invoking the system call funcion pointer. Note that
* this acts as a gateway for all system calls and serves a good point
std::string name() { return _name; }
+ protected:
+ using Executor =
+ std::function<SyscallReturn(SyscallDesc *, int num, ThreadContext *)>;
+ using Dumper = std::function<std::string(std::string, ThreadContext *)>;
+
+ SyscallDesc(const char *name, Executor exec, Dumper dump) :
+ _name(name), executor(exec), dumper(dump)
+ {}
+
private:
/** System call name (e.g., open, mmap, clone, socket, etc.) */
std::string _name;
/** Mechanism for ISAs to connect to the emul function definitions */
- SyscallExecutor executor;
+ Executor executor;
+ Dumper dumper;
};
/*
private:
// Aliases to make the code below a little more concise.
template <typename ...Args>
- using SyscallABIExecutor =
+ using ABIExecutor =
std::function<SyscallReturn(SyscallDesc *, int,
ThreadContext *, Args...)>;
template <typename ...Args>
- using SyscallABIExecutorPtr =
+ using ABIExecutorPtr =
SyscallReturn (*)(SyscallDesc *, int, 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 SyscallExecutor
- buildExecutor(SyscallABIExecutor<Args...> target)
+ static inline Executor
+ buildExecutor(ABIExecutor<Args...> target)
{
return [target](SyscallDesc *desc, int num,
ThreadContext *tc) -> SyscallReturn {
};
}
+ 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(const char *name, SyscallABIExecutor<Args...> target) :
- SyscallDesc(name, buildExecutor<Args...>(target))
+ SyscallDescABI(const char *name, ABIExecutor<Args...> target) :
+ SyscallDesc(name, buildExecutor<Args...>(target),
+ buildDumper<Args...>())
{}
template <typename ...Args>
- SyscallDescABI(const char *name, SyscallABIExecutorPtr<Args...> target) :
- SyscallDescABI(name, SyscallABIExecutor<Args...>(target))
+ SyscallDescABI(const char *name, ABIExecutorPtr<Args...> target) :
+ SyscallDescABI(name, ABIExecutor<Args...>(target))
{}
- using SyscallDesc::SyscallDesc;
+ SyscallDescABI(const char *name) :
+ SyscallDescABI(name, ABIExecutor<>(unimplementedFunc))
+ {}
};
#endif // __SIM_SYSCALL_DESC_HH__