sim: Rework the SyscallDesc to use the dumpSimcall mechanism.

This greatly simplifies the doSyscall method, removes a use of
getSyscallArg, and will only print arguments the target syscall is
going to use.

Change-Id: Id8c9c995a2506468fd99fd865f2eb31c40db8b55
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/23461
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Bobby R. Bruce <bbruce@ucdavis.edu>
Maintainer: Gabe Black <gabeblack@google.com>
This commit is contained in:
Gabe Black
2019-12-08 01:36:05 -08:00
parent 1d60aba814
commit 0b5ee2e864
2 changed files with 40 additions and 58 deletions

View File

@@ -29,54 +29,22 @@
#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();
DPRINTF_SYSCALL(Base, "Calling %s...\n", dumper(name(), tc));
/**
* 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);
/**
* 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());
}

View File

@@ -64,13 +64,6 @@ SyscallReturn unimplementedFunc(SyscallDesc *desc, int num,
*/
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
@@ -83,12 +76,22 @@ class SyscallDesc {
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;
};
/*
@@ -102,20 +105,20 @@ class SyscallDescABI : public SyscallDesc
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 {
@@ -134,20 +137,31 @@ class SyscallDescABI : public SyscallDesc
};
}
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__