arch,cpu,sim: Push syscall number determination up to processes.

The logic that determines which syscall to call was built into the
implementation of faults/exceptions or even into the instruction
decoder, but that logic can depend on what OS is being used, and
sometimes even what version, for example 32bit vs. 64bit.

This change pushes that logic up into the Process objects since those
already handle a lot of the aspects of emulating the guest OS. Instead,
the ISA or fault implementations just notify the rest of the system
that a nebulous syscall has happened, and that gets propogated upward
until the process does something with it. That's very analogous to how
a system call would work on a real machine.

When a system call happens, the low level component which detects that
should call tc->syscall(&fault), where tc is the relevant thread (or
execution) context, and fault is a Fault which can ultimately be set
by the system call implementation.

The TC implementor (probably a CPU) will then have a chance to do
whatever it needs to to handle a system call. Currently only O3 does
anything special here. That implementor will end up calling the
Process's syscall() method.

Once in Process::syscall, the process object will use it's contextual
knowledge to determine what system call is being requested. It then
calls Process::doSyscall with the right syscall number, where doSyscall
centralizes the common mechanism for actually retrieving and calling
into the system call implementation.

Jira Issue: https://gem5.atlassian.net/browse/GEM5-187

Change-Id: I937ec1ef0576142c2a182ff33ca508d77ad0e7a1
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/23176
Maintainer: Gabe Black <gabeblack@google.com>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Brandon Potter <Brandon.Potter@amd.com>
This commit is contained in:
Gabe Black
2019-11-25 01:07:41 -08:00
parent d142a1547c
commit cb3457ccd1
46 changed files with 165 additions and 77 deletions

View File

@@ -840,7 +840,7 @@ decode OPCODE default Unknown::unknown() {
exitSimLoop("halt instruction encountered");
}}, IsNonSpeculative);
0x83: callsys({{
xc->syscall(R0, &fault);
xc->syscall(&fault);
}}, IsSerializeAfter, IsNonSpeculative, IsSyscall);
// Read uniq reg into ABI return value register (r0)
0x9e: rduniq({{ R0 = Runiq; }}, IsIprAccess);

View File

@@ -620,3 +620,10 @@ AlphaLinuxProcess::getDesc(int callnum)
return NULL;
return &syscallDescs[callnum];
}
void
AlphaLinuxProcess::syscall(ThreadContext *tc, Fault *fault)
{
doSyscall(tc->readIntReg(0), tc, fault);
}

View File

@@ -42,6 +42,8 @@ class AlphaLinuxProcess : public AlphaProcess
/// Constructor.
AlphaLinuxProcess(ProcessParams * params, ObjectFile *objFile);
void syscall(ThreadContext *tc, Fault *fault) override;
virtual SyscallDesc* getDesc(int callnum);
/// Array of syscall descriptors, indexed by call number.

View File

@@ -419,7 +419,7 @@ class ThreadContext : public ::ThreadContext
}
void
syscall(int64_t callnum, Fault *fault) override
syscall(Fault *fault) override
{
panic("%s not implemented.", __FUNCTION__);
}

View File

@@ -845,15 +845,8 @@ SupervisorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst)
// As of now, there isn't a 32 bit thumb version of this instruction.
assert(!machInst.bigThumb);
uint32_t callNum;
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
OperatingMode mode = (OperatingMode)(uint8_t)cpsr.mode;
if (opModeIs64(mode))
callNum = tc->readIntReg(INTREG_X8);
else
callNum = tc->readIntReg(INTREG_R7);
Fault fault;
tc->syscall(callNum, &fault);
tc->syscall(&fault);
// Advance the PC since that won't happen automatically.
PCState pc = tc->pcState();

View File

@@ -1317,3 +1317,15 @@ ArmFreebsdProcess64::initState()
ArmProcess64::initState();
// The 64 bit equivalent of the comm page would be set up here.
}
void
ArmFreebsdProcess32::syscall(ThreadContext *tc, Fault *fault)
{
doSyscall(tc->readIntReg(INTREG_R7), tc, fault);
}
void
ArmFreebsdProcess64::syscall(ThreadContext *tc, Fault *fault)
{
doSyscall(tc->readIntReg(INTREG_X8), tc, fault);
}

View File

@@ -63,6 +63,8 @@ class ArmFreebsdProcess32 : public ArmProcess32, public ArmFreebsdProcessBits
void initState();
void syscall(ThreadContext *tc, Fault *fault) override;
/// Explicitly import the otherwise hidden getSyscallArg
using ArmProcess::getSyscallArg;
@@ -80,6 +82,7 @@ class ArmFreebsdProcess64 : public ArmProcess64, public ArmFreebsdProcessBits
ObjectFile::Arch _arch);
void initState();
void syscall(ThreadContext *tc, Fault *fault) override;
SyscallDesc* getDesc(int callnum);
};

View File

@@ -1777,3 +1777,15 @@ ArmLinuxProcess64::initState()
ArmProcess64::initState();
// The 64 bit equivalent of the comm page would be set up here.
}
void
ArmLinuxProcess32::syscall(ThreadContext *tc, Fault *fault)
{
doSyscall(tc->readIntReg(INTREG_R7), tc, fault);
}
void
ArmLinuxProcess64::syscall(ThreadContext *tc, Fault *fault)
{
doSyscall(tc->readIntReg(INTREG_X8), tc, fault);
}

View File

@@ -73,6 +73,8 @@ class ArmLinuxProcess32 : public ArmProcess32, public ArmLinuxProcessBits
void initState();
void syscall(ThreadContext *tc, Fault *fault) override;
/// Explicitly import the otherwise hidden getSyscallArg
using ArmProcess::getSyscallArg;
@@ -90,6 +92,7 @@ class ArmLinuxProcess64 : public ArmProcess64, public ArmLinuxProcessBits
ObjectFile::Arch _arch);
void initState();
void syscall(ThreadContext *tc, Fault *fault) override;
SyscallDesc* getDesc(int callnum);
};

View File

@@ -163,7 +163,7 @@ decode OPCODE_HI default Unknown::unknown() {
0x2: movz({{ Rd = (Rt == 0) ? Rs : Rd; }});
0x3: movn({{ Rd = (Rt != 0) ? Rs : Rd; }});
0x4: decode FullSystemInt {
0: syscall_se({{ xc->syscall(R2, &fault); }},
0: syscall_se({{ xc->syscall(&fault); }},
IsSerializeAfter, IsNonSpeculative);
default: syscall({{ fault = std::make_shared<SystemCallFault>(); }});
}

View File

@@ -51,9 +51,8 @@ def operands {{
#Immediate Value operand
'IntImm': ('IntReg', 'uw', 'INTIMM', 'IsInteger', 3),
#Operands used for Link or Syscall Insts
#Operands used for Link Insts
'R31': ('IntReg', 'uw','31','IsInteger', 4),
'R2': ('IntReg', 'uw','2', 'IsInteger', 5),
#Special Integer Reg operands
'LO0': ('IntReg', 'uw','INTREG_LO', 'IsInteger', 6),

View File

@@ -509,7 +509,8 @@ MipsLinuxProcess::getDesc(int callnum)
return &syscallDescs[m5_sys_idx];
}
void
MipsLinuxProcess::syscall(ThreadContext *tc, Fault *fault)
{
doSyscall(tc->readIntReg(2), tc, fault);
}

View File

@@ -51,6 +51,8 @@ class MipsLinuxProcess : public MipsProcess
/// ID of the thread group leader for the process
uint64_t __tgid;
void syscall(ThreadContext *tc, Fault *fault) override;
/// Array of syscall descriptors, indexed by call number.
static SyscallDesc syscallDescs[];
const int Num_Syscall_Descs;

View File

@@ -517,7 +517,7 @@ decode OPCODE default Unknown::unknown() {
55: stfdu({{ Mem_df = Fs; }});
}
17: IntOp::sc({{ xc->syscall(R0, &fault); }},
17: IntOp::sc({{ xc->syscall(&fault); }},
[ IsSyscall, IsNonSpeculative, IsSerializeAfter ]);
format FloatArithOp {

View File

@@ -75,7 +75,4 @@ def operands {{
'Rsv': ('IntReg', 'uw', 'INTREG_RSV', 'IsInteger', 9),
'RsvLen': ('IntReg', 'uw', 'INTREG_RSV_LEN', 'IsInteger', 9),
'RsvAddr': ('IntReg', 'uw', 'INTREG_RSV_ADDR', 'IsInteger', 9),
# Hack for non-full-system syscall emulation
'R0': ('IntReg', 'uw', '0', None, 1),
}};

View File

@@ -468,6 +468,12 @@ PowerLinuxProcess::initState()
PowerProcess::initState();
}
void
PowerLinuxProcess::syscall(ThreadContext *tc, Fault *fault)
{
doSyscall(tc->readIntReg(0), tc, fault);
}
RegVal
PowerLinuxProcess::getSyscallArg(ThreadContext *tc, int &i)
{

View File

@@ -45,6 +45,8 @@ class PowerLinuxProcess : public PowerProcess
void initState();
void syscall(ThreadContext *tc, Fault *fault) override;
RegVal getSyscallArg(ThreadContext *tc, int &i);
/// Explicitly import the otherwise hidden getSyscallArg
using Process::getSyscallArg;

View File

@@ -191,7 +191,7 @@ void
SyscallFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst)
{
Fault *fault = NoFault;
tc->syscall(tc->readIntReg(SyscallNumReg), fault);
tc->syscall(fault);
}
} // namespace RiscvISA

View File

@@ -795,6 +795,12 @@ RiscvLinuxProcess64::getDesc(int callnum)
&syscallDescs.at(callnum) : nullptr;
}
void
RiscvLinuxProcess64::syscall(ThreadContext *tc, Fault *fault)
{
doSyscall(tc->readIntReg(SyscallNumReg), tc, fault);
}
RiscvLinuxProcess32::RiscvLinuxProcess32(ProcessParams * params,
ObjectFile *objFile) : RiscvProcess32(params, objFile)
{}
@@ -805,3 +811,9 @@ RiscvLinuxProcess32::getDesc(int callnum)
return syscallDescs.find(callnum) != syscallDescs.end() ?
&syscallDescs.at(callnum) : nullptr;
}
void
RiscvLinuxProcess32::syscall(ThreadContext *tc, Fault *fault)
{
doSyscall(tc->readIntReg(SyscallNumReg), tc, fault);
}

View File

@@ -55,6 +55,8 @@ class RiscvLinuxProcess64 : public RiscvProcess64
/// ID of the thread group leader for the process
uint64_t __tgid;
void syscall(ThreadContext *tc, Fault *fault) override;
/// Array of syscall descriptors, indexed by call number.
static std::map<int, SyscallDesc> syscallDescs;
};
@@ -73,6 +75,8 @@ class RiscvLinuxProcess32 : public RiscvProcess32
/// ID of the thread group leader for the process
uint64_t __tgid;
void syscall(ThreadContext *tc, Fault *fault) override;
/// Array of syscall descriptors, indexed by call number.
static std::map<int, SyscallDesc> syscallDescs;
};

View File

@@ -100,12 +100,18 @@ Sparc32LinuxProcess::Sparc32LinuxProcess(ProcessParams * params,
: Sparc32Process(params, objFile)
{}
void Sparc32LinuxProcess::handleTrap(int trapNum, ThreadContext *tc,
Fault *fault)
void
Sparc32LinuxProcess::syscall(ThreadContext *tc, Fault *fault)
{
doSyscall(tc->readIntReg(1), tc, fault);
}
void
Sparc32LinuxProcess::handleTrap(int trapNum, ThreadContext *tc, Fault *fault)
{
switch (trapNum) {
case 0x10: //Linux 32 bit syscall trap
tc->syscall(tc->readIntReg(1), fault);
tc->syscall(fault);
break;
default:
SparcProcess::handleTrap(trapNum, tc, fault);
@@ -117,13 +123,19 @@ Sparc64LinuxProcess::Sparc64LinuxProcess(ProcessParams * params,
: Sparc64Process(params, objFile)
{}
void Sparc64LinuxProcess::handleTrap(int trapNum, ThreadContext *tc,
Fault *fault)
void
Sparc64LinuxProcess::syscall(ThreadContext *tc, Fault *fault)
{
doSyscall(tc->readIntReg(1), tc, fault);
}
void
Sparc64LinuxProcess::handleTrap(int trapNum, ThreadContext *tc, Fault *fault)
{
switch (trapNum) {
// case 0x10: // Linux 32 bit syscall trap
case 0x6d: // Linux 64 bit syscall trap
tc->syscall(tc->readIntReg(1), fault);
tc->syscall(fault);
break;
default:
SparcProcess::handleTrap(trapNum, tc, fault);

View File

@@ -70,6 +70,8 @@ class Sparc32LinuxProcess : public SparcLinuxProcess, public Sparc32Process
return SparcLinuxProcess::getDesc32(callnum);
}
void syscall(ThreadContext *tc, Fault *fault) override;
void handleTrap(int trapNum, ThreadContext *tc, Fault *fault);
};
@@ -86,6 +88,8 @@ class Sparc64LinuxProcess : public SparcLinuxProcess, public Sparc64Process
return SparcLinuxProcess::getDesc(callnum);
}
void syscall(ThreadContext *tc, Fault *fault) override;
void handleTrap(int trapNum, ThreadContext *tc, Fault *fault);
};

View File

@@ -368,3 +368,9 @@ SparcSolarisProcess::getDesc(int callnum)
return NULL;
return &syscallDescs[callnum];
}
void
SparcSolarisProcess::syscall(ThreadContext *tc, Fault *fault)
{
doSyscall(tc->readIntReg(1), tc, fault);
}

View File

@@ -49,6 +49,8 @@ class SparcSolarisProcess : public Sparc64Process
/// The target system's hostname.
static const char *hostname;
void syscall(ThreadContext *tc, Fault *fault) override;
/// Array of syscall descriptors, indexed by call number.
static SyscallDesc syscallDescs[];

View File

@@ -400,7 +400,7 @@
// will sign extend it, and there's no easy way to
// specify only checking the first byte.
0xffffffffffffff80:
SyscallInst::int80('xc->syscall(Rax, &fault)',
SyscallInst::int80('xc->syscall(&fault)',
IsSyscall, IsNonSpeculative,
IsSerializeAfter);
}

View File

@@ -235,7 +235,7 @@
}
}
0x05: decode FullSystemInt {
0: SyscallInst::syscall('xc->syscall(Rax, &fault)',
0: SyscallInst::syscall('xc->syscall(&fault)',
IsSyscall, IsNonSpeculative,
IsSerializeAfter);
default: decode MODE_MODE {
@@ -429,7 +429,7 @@
0x2: Inst::RDMSR();
0x3: rdpmc();
0x4: decode FullSystemInt {
0: SyscallInst::sysenter('xc->syscall(Rax, &fault)',
0: SyscallInst::sysenter('xc->syscall(&fault)',
IsSyscall, IsNonSpeculative,
IsSerializeAfter);
default: sysenter();

View File

@@ -584,8 +584,15 @@ X86_64LinuxProcess::X86_64LinuxProcess(ProcessParams * params,
sizeof(syscallDescs64) / sizeof(SyscallDesc))
{}
void X86_64LinuxProcess::clone(ThreadContext *old_tc, ThreadContext *new_tc,
Process *process, RegVal flags)
void
X86_64LinuxProcess::syscall(ThreadContext *tc, Fault *fault)
{
doSyscall(tc->readIntReg(INTREG_RAX), tc, fault);
}
void
X86_64LinuxProcess::clone(ThreadContext *old_tc, ThreadContext *new_tc,
Process *process, RegVal flags)
{
X86_64Process::clone(old_tc, new_tc, (X86_64Process*)process, flags);
}
@@ -926,8 +933,22 @@ I386LinuxProcess::I386LinuxProcess(ProcessParams * params, ObjectFile *objFile)
sizeof(syscallDescs32) / sizeof(SyscallDesc))
{}
void I386LinuxProcess::clone(ThreadContext *old_tc, ThreadContext *new_tc,
Process *process, RegVal flags)
void
I386LinuxProcess::syscall(ThreadContext *tc, Fault *fault)
{
PCState pc = tc->pcState();
Addr eip = pc.pc();
if (eip >= vsyscallPage.base &&
eip < vsyscallPage.base + vsyscallPage.size) {
pc.npc(vsyscallPage.base + vsyscallPage.vsysexitOffset);
tc->pcState(pc);
}
doSyscall(tc->readIntReg(INTREG_RAX), tc, fault);
}
void
I386LinuxProcess::clone(ThreadContext *old_tc, ThreadContext *new_tc,
Process *process, RegVal flags)
{
I386Process::clone(old_tc, new_tc, (I386Process*)process, flags);
}

View File

@@ -54,6 +54,7 @@ class X86_64LinuxProcess : public X86_64Process
public:
/// Constructor.
X86_64LinuxProcess(ProcessParams * params, ObjectFile *objFile);
void syscall(ThreadContext *tc, Fault *fault) override;
void clone(ThreadContext *old_tc, ThreadContext *new_tc, Process *process,
RegVal flags);
};
@@ -63,6 +64,7 @@ class I386LinuxProcess : public I386Process
public:
/// Constructor.
I386LinuxProcess(ProcessParams * params, ObjectFile *objFile);
void syscall(ThreadContext *tc, Fault *fault) override;
void clone(ThreadContext *old_tc, ThreadContext *new_tc, Process *process,
RegVal flags);
};

View File

@@ -146,19 +146,6 @@ X86_64Process::X86_64Process(ProcessParams *params, ObjectFile *objFile,
next_thread_stack_base, mmap_end);
}
void
I386Process::syscall(int64_t callnum, ThreadContext *tc, Fault *fault)
{
PCState pc = tc->pcState();
Addr eip = pc.pc();
if (eip >= vsyscallPage.base &&
eip < vsyscallPage.base + vsyscallPage.size) {
pc.npc(vsyscallPage.base + vsyscallPage.vsysexitOffset);
tc->pcState(pc);
}
X86Process::syscall(callnum, tc, fault);
}
I386Process::I386Process(ProcessParams *params, ObjectFile *objFile,
SyscallDesc *_syscallDescs, int _numSyscallDescs)

View File

@@ -176,8 +176,6 @@ namespace X86ISA
void argsInit(int pageSize);
void initState() override;
void syscall(int64_t callnum, ThreadContext *tc,
Fault *fault) override;
RegVal getSyscallArg(ThreadContext *tc, int &i) override;
RegVal getSyscallArg(ThreadContext *tc, int &i, int width) override;
void clone(ThreadContext *old_tc, ThreadContext *new_tc,

View File

@@ -50,7 +50,7 @@ m5Syscall(ThreadContext *tc)
DPRINTF(PseudoInst, "PseudoInst::m5Syscall()\n");
Fault fault;
tc->syscall(tc->readIntReg(INTREG_RAX), &fault);
tc->syscall(&fault);
}
/*

View File

@@ -581,7 +581,7 @@ class CheckerCPU : public BaseCPU, public ExecContext
void wakeup(ThreadID tid) override { }
// Assume that the normal CPU's call to syscall was successful.
// The checker's state would have already been updated by the syscall.
void syscall(int64_t callnum, Fault *fault) override { }
void syscall(Fault *fault) override { }
void
handleError()

View File

@@ -184,9 +184,9 @@ class CheckerThreadContext : public ThreadContext
/** Executes a syscall in SE mode. */
void
syscall(int64_t callnum, Fault *fault) override
syscall(Fault *fault) override
{
return actualTC->syscall(callnum, fault);
return actualTC->syscall(fault);
}
Status status() const override { return actualTC->status(); }

View File

@@ -304,9 +304,9 @@ class ExecContext {
*/
/**
* Executes a syscall specified by the callnum.
* Executes a syscall.
*/
virtual void syscall(int64_t callnum, Fault *fault) = 0;
virtual void syscall(Fault *fault) = 0;
/** @} */

View File

@@ -387,9 +387,9 @@ class ExecContext : public ::ExecContext
}
void
syscall(int64_t callnum, Fault *fault) override
syscall(Fault *fault) override
{
thread.syscall(callnum, fault);
thread.syscall(fault);
}
ThreadContext *tcBase() override { return thread.getTC(); }

View File

@@ -918,7 +918,7 @@ FullO3CPU<Impl>::trap(const Fault &fault, ThreadID tid,
template <class Impl>
void
FullO3CPU<Impl>::syscall(int64_t callnum, ThreadID tid, Fault *fault)
FullO3CPU<Impl>::syscall(ThreadID tid, Fault *fault)
{
DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid);
@@ -929,7 +929,7 @@ FullO3CPU<Impl>::syscall(int64_t callnum, ThreadID tid, Fault *fault)
++(this->thread[tid]->funcExeInst);
// Execute the actual syscall.
this->thread[tid]->syscall(callnum, fault);
this->thread[tid]->syscall(fault);
// Decrease funcExeInst by one as the normal commit will handle
// incrementing it.

View File

@@ -284,7 +284,7 @@ class FullO3CPU : public BaseO3CPU
/** Executes a syscall.
* @todo: Determine if this needs to be virtual.
*/
void syscall(int64_t callnum, ThreadID tid, Fault *fault);
void syscall(ThreadID tid, Fault *fault);
/** Starts draining the CPU's pipeline of all instructions in
* order to stop all memory accesses. */

View File

@@ -252,7 +252,7 @@ class BaseO3DynInst : public BaseDynInst<Impl>
void trap(const Fault &fault);
/** Emulates a syscall. */
void syscall(int64_t callnum, Fault *fault) override;
void syscall(Fault *fault) override;
public:

View File

@@ -192,13 +192,13 @@ BaseO3DynInst<Impl>::trap(const Fault &fault)
template <class Impl>
void
BaseO3DynInst<Impl>::syscall(int64_t callnum, Fault *fault)
BaseO3DynInst<Impl>::syscall(Fault *fault)
{
// HACK: check CPU's nextPC before and after syscall. If it
// changes, update this instruction's nextPC because the syscall
// must have changed the nextPC.
TheISA::PCState curPC = this->cpu->pcState(this->threadNumber);
this->cpu->syscall(callnum, this->threadNumber, fault);
this->cpu->syscall(this->threadNumber, fault);
TheISA::PCState newPC = this->cpu->pcState(this->threadNumber);
if (!(curPC == newPC)) {
this->pcState(newPC);

View File

@@ -448,9 +448,9 @@ class O3ThreadContext : public ThreadContext
/** Executes a syscall in SE mode. */
void
syscall(int64_t callnum, Fault *fault) override
syscall(Fault *fault) override
{
return cpu->syscall(callnum, thread->threadId(), fault);
return cpu->syscall(thread->threadId(), fault);
}
/** Reads the funcExeInst counter. */

View File

@@ -148,10 +148,9 @@ struct O3ThreadState : public ThreadState {
ThreadContext *getTC() { return tc; }
/** Handles the syscall. */
void syscall(int64_t callnum, Fault *fault)
void syscall(Fault *fault)
{
fatal_if(FullSystem, "System call emulation is unavailable!");
process->syscall(callnum, tc, fault);
process->syscall(tc, fault);
}
void dumpFuncProfile()

View File

@@ -497,9 +497,9 @@ class SimpleExecContext : public ExecContext {
* Executes a syscall specified by the callnum.
*/
void
syscall(int64_t callnum, Fault *fault) override
syscall(Fault *fault) override
{
thread->syscall(callnum, fault);
thread->syscall(fault);
}
/** Returns a pointer to the ThreadContext. */

View File

@@ -609,10 +609,9 @@ class SimpleThread : public ThreadState, public ThreadContext
}
void
syscall(int64_t callnum, Fault *fault) override
syscall(Fault *fault) override
{
fatal_if(FullSystem, "System call emulation is unavailable!");
process->syscall(callnum, this, fault);
process->syscall(this, fault);
}
RegVal readIntRegFlat(RegIndex idx) const override { return intRegs[idx]; }

View File

@@ -307,7 +307,7 @@ class ThreadContext : public PCEventScope
// Same with st cond failures.
virtual Counter readFuncExeInst() const = 0;
virtual void syscall(int64_t callnum, Fault *fault) = 0;
virtual void syscall(Fault *fault) = 0;
// This function exits the thread context in the CPU and returns
// 1 if the CPU has no more active threads (meaning it's OK to exit);

View File

@@ -437,7 +437,7 @@ Process::map(Addr vaddr, Addr paddr, int size, bool cacheable)
}
void
Process::syscall(int64_t callnum, ThreadContext *tc, Fault *fault)
Process::doSyscall(int64_t callnum, ThreadContext *tc, Fault *fault)
{
numSyscalls++;

View File

@@ -63,6 +63,9 @@ class ThreadContext;
class Process : public SimObject
{
protected:
void doSyscall(int64_t callnum, ThreadContext *tc, Fault *fault);
public:
Process(ProcessParams *params, EmulationPageTable *pTable,
ObjectFile *obj_file);
@@ -74,7 +77,7 @@ class Process : public SimObject
void initState() override;
DrainState drain() override;
virtual void syscall(int64_t callnum, ThreadContext *tc, Fault *fault);
virtual void syscall(ThreadContext *tc, Fault *fault) = 0;
virtual RegVal getSyscallArg(ThreadContext *tc, int &i) = 0;
virtual RegVal getSyscallArg(ThreadContext *tc, int &i, int width);
virtual void setSyscallReturn(ThreadContext *tc,