# Node ID 2f88471df39aa3ebb7784260df724ec08e245235 # Parent a511f29b73b26784cf058a9a8aebb62a66acf426 diff --git a/src/arch/alpha/isa/decoder.isa b/src/arch/alpha/isa/decoder.isa --- a/src/arch/alpha/isa/decoder.isa +++ b/src/arch/alpha/isa/decoder.isa @@ -840,7 +840,7 @@ exitSimLoop("halt instruction encountered"); }}, IsNonSpeculative); 0x83: callsys({{ - xc->syscall(R0); + xc->syscall(R0, &fault); }}, IsSerializeAfter, IsNonSpeculative, IsSyscall); // Read uniq reg into ABI return value register (r0) 0x9e: rduniq({{ R0 = Runiq; }}, IsIprAccess); diff --git a/src/arch/arm/faults.hh b/src/arch/arm/faults.hh --- a/src/arch/arm/faults.hh +++ b/src/arch/arm/faults.hh @@ -296,7 +296,7 @@ overrideEc(_overrideEc) {} - void invoke(ThreadContext *tc, const StaticInstPtr &inst = + void invoke(ThreadContext *tc, Fault *fault, const StaticInstPtr &inst = StaticInst::nullStaticInstPtr); bool routeToHyp(ThreadContext *tc) const; ExceptionClass ec(ThreadContext *tc) const; diff --git a/src/arch/arm/faults.cc b/src/arch/arm/faults.cc --- a/src/arch/arm/faults.cc +++ b/src/arch/arm/faults.cc @@ -768,7 +768,8 @@ } void -SupervisorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst) +SupervisorCall::invoke(ThreadContext *tc, Fault *fault, + const StaticInstPtr &inst) { if (FullSystem) { ArmFault::invoke(tc, inst); @@ -784,7 +785,7 @@ callNum = tc->readIntReg(INTREG_X8); else callNum = tc->readIntReg(INTREG_R7); - tc->syscall(callNum); + tc->syscall(callNum, fault); // Advance the PC since that won't happen automatically. PCState pc = tc->pcState(); diff --git a/src/arch/mips/isa/decoder.isa b/src/arch/mips/isa/decoder.isa --- a/src/arch/mips/isa/decoder.isa +++ b/src/arch/mips/isa/decoder.isa @@ -164,7 +164,7 @@ 0x2: movz({{ Rd = (Rt == 0) ? Rs : Rd; }}); 0x3: movn({{ Rd = (Rt != 0) ? Rs : Rd; }}); 0x4: decode FullSystemInt { - 0: syscall_se({{ xc->syscall(R2); }}, + 0: syscall_se({{ xc->syscall(R2, &fault); }}, IsSerializeAfter, IsNonSpeculative); default: syscall({{ fault = std::make_shared(); }}); } diff --git a/src/arch/power/isa/decoder.isa b/src/arch/power/isa/decoder.isa --- a/src/arch/power/isa/decoder.isa +++ b/src/arch/power/isa/decoder.isa @@ -512,7 +512,7 @@ 55: stfdu({{ Mem_df = Fs; }}); } - 17: IntOp::sc({{ xc->syscall(R0); }}, + 17: IntOp::sc({{ xc->syscall(R0, &fault); }}, [ IsSyscall, IsNonSpeculative, IsSerializeAfter ]); format FloatArithOp { diff --git a/src/arch/riscv/faults.cc b/src/arch/riscv/faults.cc --- a/src/arch/riscv/faults.cc +++ b/src/arch/riscv/faults.cc @@ -87,5 +87,6 @@ void SyscallFault::invoke_se(ThreadContext *tc, const StaticInstPtr &inst) { - tc->syscall(tc->readIntReg(SyscallNumReg)); + Fault *fault = NoFault; + tc->syscall(tc->readIntReg(SyscallNumReg), fault); } diff --git a/src/arch/sparc/linux/process.hh b/src/arch/sparc/linux/process.hh --- a/src/arch/sparc/linux/process.hh +++ b/src/arch/sparc/linux/process.hh @@ -70,7 +70,7 @@ return SparcLinuxProcess::getDesc32(callnum); } - void handleTrap(int trapNum, ThreadContext *tc); + void handleTrap(int trapNum, ThreadContext *tc, Fault *fault); }; /// A process with emulated 32 bit SPARC/Linux syscalls. @@ -86,7 +86,7 @@ return SparcLinuxProcess::getDesc(callnum); } - void handleTrap(int trapNum, ThreadContext *tc); + void handleTrap(int trapNum, ThreadContext *tc, Fault *fault); }; SyscallReturn getresuidFunc(SyscallDesc *desc, int num, diff --git a/src/arch/sparc/linux/process.cc b/src/arch/sparc/linux/process.cc --- a/src/arch/sparc/linux/process.cc +++ b/src/arch/sparc/linux/process.cc @@ -65,11 +65,12 @@ : Sparc32Process(params, objFile) {} -void Sparc32LinuxProcess::handleTrap(int trapNum, ThreadContext *tc) +void Sparc32LinuxProcess::handleTrap(int trapNum, ThreadContext *tc, + Fault *fault) { switch (trapNum) { case 0x10: //Linux 32 bit syscall trap - tc->syscall(tc->readIntReg(1)); + tc->syscall(tc->readIntReg(1), fault); break; default: SparcProcess::handleTrap(trapNum, tc); @@ -81,12 +82,13 @@ : Sparc64Process(params, objFile) {} -void Sparc64LinuxProcess::handleTrap(int trapNum, ThreadContext *tc) +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)); + tc->syscall(tc->readIntReg(1), fault); break; default: SparcProcess::handleTrap(trapNum, tc); diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa --- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa @@ -400,8 +400,9 @@ // will sign extend it, and there's no easy way to // specify only checking the first byte. 0xffffffffffffff80: - SyscallInst::int80('xc->syscall(Rax)', - IsSyscall, IsNonSpeculative, IsSerializeAfter); + SyscallInst::int80('xc->syscall(Rax, &fault)', + IsSyscall, IsNonSpeculative, + IsSerializeAfter); } default: Inst::INT(Ib); diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -235,8 +235,9 @@ } } 0x05: decode FullSystemInt { - 0: SyscallInst::syscall('xc->syscall(Rax)', - IsSyscall, IsNonSpeculative, IsSerializeAfter); + 0: SyscallInst::syscall('xc->syscall(Rax, &fault)', + IsSyscall, IsNonSpeculative, + IsSerializeAfter); default: decode MODE_MODE { 0x0: decode MODE_SUBMODE { 0x0: Inst::SYSCALL_64(); @@ -422,8 +423,9 @@ 0x2: Inst::RDMSR(); 0x3: rdpmc(); 0x4: decode FullSystemInt { - 0: SyscallInst::sysenter('xc->syscall(Rax)', - IsSyscall, IsNonSpeculative, IsSerializeAfter); + 0: SyscallInst::sysenter('xc->syscall(Rax, &fault)', + IsSyscall, IsNonSpeculative, + IsSerializeAfter); default: sysenter(); } 0x5: sysexit(); diff --git a/src/arch/x86/process.hh b/src/arch/x86/process.hh --- a/src/arch/x86/process.hh +++ b/src/arch/x86/process.hh @@ -130,7 +130,7 @@ void argsInit(int intSize, int pageSize); void initState(); - void syscall(int64_t callnum, ThreadContext *tc); + void syscall(int64_t callnum, ThreadContext *tc, Fault *fault); X86ISA::IntReg getSyscallArg(ThreadContext *tc, int &i); X86ISA::IntReg getSyscallArg(ThreadContext *tc, int &i, int width); void setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val); diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -134,7 +134,7 @@ } void -I386Process::syscall(int64_t callnum, ThreadContext *tc) +I386Process::syscall(int64_t callnum, ThreadContext *tc, Fault *fault) { TheISA::PCState pc = tc->pcState(); Addr eip = pc.pc(); @@ -143,7 +143,7 @@ pc.npc(vsyscallPage.base + vsyscallPage.vsysexitOffset); tc->pcState(pc); } - X86Process::syscall(callnum, tc); + X86Process::syscall(callnum, tc, fault); } diff --git a/src/arch/x86/pseudo_inst.cc b/src/arch/x86/pseudo_inst.cc --- a/src/arch/x86/pseudo_inst.cc +++ b/src/arch/x86/pseudo_inst.cc @@ -49,7 +49,9 @@ { DPRINTF(PseudoInst, "PseudoInst::m5Syscall()\n"); - tc->syscall(tc->readIntReg(INTREG_RAX)); + Fault fault; + tc->syscall(tc->readIntReg(INTREG_RAX), &fault); + MiscReg rflags = tc->readMiscReg(MISCREG_RFLAGS); rflags &= ~(1 << 16); tc->setMiscReg(MISCREG_RFLAGS, rflags); diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py --- a/src/cpu/BaseCPU.py +++ b/src/cpu/BaseCPU.py @@ -142,6 +142,8 @@ checker = Param.BaseCPU(NULL, "checker CPU") + syscallRetryLatency = Param.Cycles(10000, "Cycles to wait until retry") + do_checkpoint_insts = Param.Bool(True, "enable checkpoint pseudo instructions") do_statistics_insts = Param.Bool(True, diff --git a/src/cpu/base.hh b/src/cpu/base.hh --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -588,6 +588,8 @@ assert(tid < numThreads); return &addressMonitor[tid]; } + + Cycles syscallRetryLatency; }; #endif // THE_ISA == NULL_ISA diff --git a/src/cpu/base.cc b/src/cpu/base.cc --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -135,7 +135,8 @@ numThreads(p->numThreads), system(p->system), functionTraceStream(nullptr), currentFunctionStart(0), currentFunctionEnd(0), functionEntryTick(0), - addressMonitor(p->numThreads) + addressMonitor(p->numThreads), + syscallRetryLatency(p->syscallRetryLatency) { // if Python did not provide a valid ID, do it here if (_cpuId == -1 ) { diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@ -393,7 +393,7 @@ 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) override { } + void syscall(int64_t callnum, Fault *fault) override { } void handleError() { diff --git a/src/cpu/checker/thread_context.hh b/src/cpu/checker/thread_context.hh --- a/src/cpu/checker/thread_context.hh +++ b/src/cpu/checker/thread_context.hh @@ -146,8 +146,8 @@ SETranslatingPortProxy &getMemProxy() { return actualTC->getMemProxy(); } /** Executes a syscall in SE mode. */ - void syscall(int64_t callnum) - { return actualTC->syscall(callnum); } + void syscall(int64_t callnum, Fault *fault) + { return actualTC->syscall(callnum, fault); } Status status() const { return actualTC->status(); } diff --git a/src/cpu/exec_context.hh b/src/cpu/exec_context.hh --- a/src/cpu/exec_context.hh +++ b/src/cpu/exec_context.hh @@ -228,7 +228,7 @@ /** * Executes a syscall specified by the callnum. */ - virtual void syscall(int64_t callnum) = 0; + virtual void syscall(int64_t callnum, Fault *fault) = 0; /** @} */ diff --git a/src/cpu/minor/exec_context.hh b/src/cpu/minor/exec_context.hh --- a/src/cpu/minor/exec_context.hh +++ b/src/cpu/minor/exec_context.hh @@ -241,12 +241,12 @@ } void - syscall(int64_t callnum) override + syscall(int64_t callnum, Fault *fault) override { if (FullSystem) panic("Syscall emulation isn't available in FS mode.\n"); - thread.syscall(callnum); + thread.syscall(callnum, fault); } ThreadContext *tcBase() override { return thread.getTC(); } diff --git a/src/cpu/o3/commit.hh b/src/cpu/o3/commit.hh --- a/src/cpu/o3/commit.hh +++ b/src/cpu/o3/commit.hh @@ -235,7 +235,7 @@ size_t numROBFreeEntries(ThreadID tid); /** Generates an event to schedule a squash due to a trap. */ - void generateTrapEvent(ThreadID tid); + void generateTrapEvent(ThreadID tid, Fault inst_fault); /** Records that commit needs to initiate a squash due to an * external state update through the TC. diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -526,13 +526,16 @@ template void -DefaultCommit::generateTrapEvent(ThreadID tid) +DefaultCommit::generateTrapEvent(ThreadID tid, Fault inst_fault) { DPRINTF(Commit, "Generating trap event for [tid:%i]\n", tid); TrapEvent *trap = new TrapEvent(this, tid); - cpu->schedule(trap, cpu->clockEdge(trapLatency)); + Cycles latency = dynamic_pointer_cast(inst_fault) ? + cpu->syscallRetryLatency : trapLatency; + + cpu->schedule(trap, cpu->clockEdge(latency)); trapInFlight[tid] = true; thread[tid]->trapPending = true; } @@ -767,10 +770,11 @@ commitStatus[0] = TrapPending; + interrupt = NoFault; + // Generate trap squash event. - generateTrapEvent(0); + generateTrapEvent(0, interrupt); - interrupt = NoFault; avoidQuiesceLiveLock = false; } else { DPRINTF(Commit, "Interrupt pending: instruction is %sin " @@ -1240,7 +1244,7 @@ } // Generate trap squash event. - generateTrapEvent(tid); + generateTrapEvent(tid, inst_fault); return false; } diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -344,7 +344,7 @@ /** Executes a syscall. * @todo: Determine if this needs to be virtual. */ - void syscall(int64_t callnum, ThreadID tid); + void syscall(int64_t callnum, ThreadID tid, Fault *fault); /** Starts draining the CPU's pipeline of all instructions in * order to stop all memory accesses. */ diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -972,7 +972,7 @@ template void -FullO3CPU::syscall(int64_t callnum, ThreadID tid) +FullO3CPU::syscall(int64_t callnum, ThreadID tid, Fault *fault) { DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid); @@ -983,7 +983,7 @@ ++(this->thread[tid]->funcExeInst); // Execute the actual syscall. - this->thread[tid]->syscall(callnum); + this->thread[tid]->syscall(callnum, fault); // Decrease funcExeInst by one as the normal commit will handle // incrementing it. diff --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh --- a/src/cpu/o3/dyn_inst.hh +++ b/src/cpu/o3/dyn_inst.hh @@ -237,7 +237,7 @@ bool simPalCheck(int palFunc); /** Emulates a syscall. */ - void syscall(int64_t callnum); + void syscall(int64_t callnum, Fault *fault); public: diff --git a/src/cpu/o3/dyn_inst_impl.hh b/src/cpu/o3/dyn_inst_impl.hh --- a/src/cpu/o3/dyn_inst_impl.hh +++ b/src/cpu/o3/dyn_inst_impl.hh @@ -242,7 +242,7 @@ template void -BaseO3DynInst::syscall(int64_t callnum) +BaseO3DynInst::syscall(int64_t callnum, Fault *fault) { if (FullSystem) panic("Syscall emulation isn't available in FS mode.\n"); @@ -251,7 +251,7 @@ // 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); + this->cpu->syscall(callnum, this->threadNumber, fault); TheISA::PCState newPC = this->cpu->pcState(this->threadNumber); if (!(curPC == newPC)) { this->pcState(newPC); diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -258,8 +258,8 @@ { thread->storeCondFailures = sc_failures; } /** Executes a syscall in SE mode. */ - virtual void syscall(int64_t callnum) - { return cpu->syscall(callnum, thread->threadId()); } + virtual void syscall(int64_t callnum, Fault *fault) + { return cpu->syscall(callnum, thread->threadId(), fault); } /** Reads the funcExeInst counter. */ virtual Counter readFuncExeInst() { return thread->funcExeInst; } diff --git a/src/cpu/o3/thread_state.hh b/src/cpu/o3/thread_state.hh --- a/src/cpu/o3/thread_state.hh +++ b/src/cpu/o3/thread_state.hh @@ -140,7 +140,10 @@ ThreadContext *getTC() { return tc; } /** Handles the syscall. */ - void syscall(int64_t callnum) { process->syscall(callnum, tc); } + void syscall(int64_t callnum, Fault *fault) + { + process->syscall(callnum, tc, fault); + } void dumpFuncProfile() { diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -628,6 +628,7 @@ preExecute(); + Tick stall_ticks = 0; if (curStaticInst) { fault = curStaticInst->execute(&t_info, traceData); @@ -641,6 +642,13 @@ traceData = NULL; } + if (dynamic_pointer_cast(fault)) { + // Retry execution of system calls after a delay. + // Prevents immediate re-execution since conditions which + // caused the retry are unlikely to change every tick. + stall_ticks += clockEdge(syscallRetryLatency) - curTick(); + } + postExecute(); } @@ -649,7 +657,6 @@ curStaticInst->isFirstMicroop())) instCnt++; - Tick stall_ticks = 0; if (simulate_inst_stalls && icache_access) stall_ticks += icache_latency; diff --git a/src/cpu/simple/exec_context.hh b/src/cpu/simple/exec_context.hh --- a/src/cpu/simple/exec_context.hh +++ b/src/cpu/simple/exec_context.hh @@ -323,12 +323,12 @@ /** * Executes a syscall specified by the callnum. */ - void syscall(int64_t callnum) override + void syscall(int64_t callnum, Fault *fault) override { if (FullSystem) panic("Syscall emulation isn't available in FS mode."); - thread->syscall(callnum); + thread->syscall(callnum, fault); } /** Returns a pointer to the ThreadContext. */ diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -670,9 +670,15 @@ return; if (fault != NoFault) { + DPRINTF(SimpleCPU, "Fault occured, scheduling fetch event\n"); + advancePC(fault); - DPRINTF(SimpleCPU, "Fault occured, scheduling fetch event\n"); - reschedule(fetchEvent, clockEdge(), true); + + Tick stall = dynamic_pointer_cast(fault) ? + clockEdge(syscallRetryLatency) : clockEdge(); + + reschedule(fetchEvent, stall, true); + _status = Faulting; return; } diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -424,9 +424,9 @@ void setStCondFailures(unsigned sc_failures) { storeCondFailures = sc_failures; } - void syscall(int64_t callnum) + void syscall(int64_t callnum, Fault *fault) { - process->syscall(callnum, tc); + process->syscall(callnum, tc, fault); } uint64_t readIntRegFlat(int idx) { return intRegs[idx]; } diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -264,7 +264,7 @@ // Same with st cond failures. virtual Counter readFuncExeInst() = 0; - virtual void syscall(int64_t callnum) = 0; + virtual void syscall(int64_t callnum, 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); @@ -471,8 +471,8 @@ void setStCondFailures(unsigned sc_failures) { actualTC->setStCondFailures(sc_failures); } - void syscall(int64_t callnum) - { actualTC->syscall(callnum); } + void syscall(int64_t callnum, Fault *fault) + { actualTC->syscall(callnum, fault); } Counter readFuncExeInst() { return actualTC->readFuncExeInst(); } diff --git a/src/sim/faults.hh b/src/sim/faults.hh --- a/src/sim/faults.hh +++ b/src/sim/faults.hh @@ -72,6 +72,22 @@ StaticInst::nullStaticInstPtr); }; +/* + * This class is needed to allow system call retries to occur for blocking + * system calls in SE mode. A retry fault will be generated by the system call + * emulation code if blocking conditions arise; the fault is passed up the + * function call chain into the CPU model where it is handled by retrying the + * syscall instruction on a later tick. + */ +class SyscallRetryFault : public FaultBase +{ + public: + virtual FaultName name() const { return "System call retry fault"; } + SyscallRetryFault() {} + void invoke(ThreadContext *tc, const StaticInstPtr &inst = + StaticInst::nullStaticInstPtr); +}; + class GenericPageTableFault : public FaultBase { private: diff --git a/src/sim/faults.cc b/src/sim/faults.cc --- a/src/sim/faults.cc +++ b/src/sim/faults.cc @@ -59,6 +59,11 @@ tc->pcState(tc->pcState()); } +void SyscallRetryFault::invoke(ThreadContext *tc, const StaticInstPtr &inst) +{ + tc->pcState(tc->pcState()); +} + void GenericPageTableFault::invoke(ThreadContext *tc, const StaticInstPtr &inst) { bool handled = false; diff --git a/src/sim/process.hh b/src/sim/process.hh --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -80,7 +80,7 @@ void initState() override; DrainState drain() override; - void syscall(int64_t callnum, ThreadContext *tc); + void syscall(int64_t callnum, ThreadContext *tc, Fault *fault); virtual TheISA::IntReg getSyscallArg(ThreadContext *tc, int &i) = 0; virtual TheISA::IntReg getSyscallArg(ThreadContext *tc, int &i, int width); virtual void setSyscallArg(ThreadContext *tc, int i, diff --git a/src/sim/process.cc b/src/sim/process.cc --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -269,7 +269,7 @@ } void -Process::syscall(int64_t callnum, ThreadContext *tc) +Process::syscall(int64_t callnum, ThreadContext *tc, Fault *fault) { num_syscalls++; @@ -277,7 +277,7 @@ if (desc == NULL) fatal("Syscall %d out of range", callnum); - desc->doSyscall(callnum, this, tc); + desc->doSyscall(callnum, this, tc, fault); } IntReg diff --git a/src/sim/syscall_desc.hh b/src/sim/syscall_desc.hh --- a/src/sim/syscall_desc.hh +++ b/src/sim/syscall_desc.hh @@ -48,6 +48,8 @@ #include +#include "base/types.hh" + class Process; class SyscallReturn; class ThreadContext; @@ -91,7 +93,8 @@ * @param proc Handle for the owning Process to pass information * @param tc Handle for owning ThreadContext to pass information */ - void doSyscall(int callnum, Process *proc, ThreadContext *tc); + void doSyscall(int callnum, Process *proc, ThreadContext *tc, + Fault *fault); /** * Return false if WarnOnce is set and a warning has already been issued. diff --git a/src/sim/syscall_desc.cc b/src/sim/syscall_desc.cc --- a/src/sim/syscall_desc.cc +++ b/src/sim/syscall_desc.cc @@ -33,16 +33,21 @@ #include "sim/syscall_desc.hh" +#include + #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" #include "sim/syscall_return.hh" void -SyscallDesc::doSyscall(int callnum, Process *process, ThreadContext *tc) +SyscallDesc::doSyscall(int callnum, Process *process, ThreadContext *tc, + Fault *fault) { TheISA::IntReg arg[6] M5_VAR_USED; @@ -71,9 +76,10 @@ * blocking behavior, warn that the system call will retry; * alternatively, print the return value. */ - if (retval.needsRetry()) + if (retval.needsRetry()) { + *fault = std::make_shared(); DPRINTF_SYSCALL(Base, "%s needs retry\n", _name); - else + } else DPRINTF_SYSCALL(Base, "%s returns %d\n", _name, retval.encodedValue()); if (!(_flags & SyscallDesc::SuppressReturnValue) && !retval.needsRetry())