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:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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__);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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>(); }});
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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),
|
||||
}};
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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[];
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -50,7 +50,7 @@ m5Syscall(ThreadContext *tc)
|
||||
DPRINTF(PseudoInst, "PseudoInst::m5Syscall()\n");
|
||||
|
||||
Fault fault;
|
||||
tc->syscall(tc->readIntReg(INTREG_RAX), &fault);
|
||||
tc->syscall(&fault);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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(); }
|
||||
|
||||
@@ -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;
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
@@ -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(); }
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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]; }
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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++;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user